Make a parameter subsitution in bash aliases for ssh - bash

Is there a way I can create a alias for this command and have it ask for the host.
ssh -i .ssh/name.pem root#
Thx

Something like the following should work (not tested)
sshfunction(){
echo "Specify your hostname:"
read host
ssh -i .ssh/name.pem root#"$host"
}
Then:
$ sshfunction
Though if it was me, I'd just provide the hostname as a variable and cut-out the middle man.
Better yet, populate your ~/.ssh/config file (if it doesn't exist you can just create it):
host MyHostName
Hostname 123.456.7.89
User username
Then:
$ ssh MyHostName

Related

Secure copy over two IPs on the same network to the local machine [duplicate]

I wonder if there is a way for me to SCP the file from remote2 host directly from my local machine by going through a remote1 host.
The networks only allow connections to remote2 host from remote1 host. Also, neither remote1 host nor remote2 host can scp to my local machine.
Is there something like:
scp user1#remote1:user2#remote2:file .
First window: ssh remote1, then scp remot2:file ..
Second shell: scp remote1:file .
First window: rm file; logout
I could write a script to do all these steps, but if there is a direct way, I would rather use it.
Thanks.
EDIT: I am thinking something like opening SSH tunnels but i'm confused on what value to put where.
At the moment, to access remote1, i have the following in $HOME/.ssh/config on my local machine.
Host remote1
User user1
Hostname localhost
Port 45678
Once on remote1, to access remote2, it's the standard local DNS and port 22. What should I put on remote1 and/or change on localhost?
I don't know of any way to copy the file directly in one single command, but if you can concede to running an SSH instance in the background to just keep a port forwarding tunnel open, then you could copy the file in one command.
Like this:
# First, open the tunnel
ssh -L 1234:remote2:22 -p 45678 user1#remote1
# Then, use the tunnel to copy the file directly from remote2
scp -P 1234 user2#localhost:file .
Note that you connect as user2#localhost in the actual scp command, because it is on port 1234 on localhost that the first ssh instance is listening to forward connections to remote2. Note also that you don't need to run the first command for every subsequent file copy; you can simply leave it running.
Double ssh
Even in your complex case, you can handle file transfer using a single command line, simply with ssh ;-)
And this is useful if remote1 cannot connect to localhost:
ssh user1#remote1 'ssh user2#remote2 "cat file"' > file
tar
But you loose file properties (ownership, permissions...).
However, tar is your friend to keep these file properties:
ssh user1#remote1 'ssh user2#remote2 "cd path2; tar c file"' | tar x
You can also compress to reduce network bandwidth:
ssh user1#remote1 'ssh user2#remote2 "cd path2; tar cj file"' | tar xj
And tar also allows you transferring a recursive directory through basic ssh:
ssh user1#remote1 'ssh user2#remote2 "cd path2; tar cj ."' | tar xj
ionice
If the file is huge and you do not want to disturb other important network applications, you may miss network throughput limitation provided by scp and rsync tools (e.g. scp -l 1024 user#remote:file does not use more than 1 Mbits/second).
But, a workaround is using ionice to keep a single command line:
ionice -c2 -n7 ssh u1#remote1 'ionice -c2 -n7 ssh u2#remote2 "cat file"' > file
Note: ionice may not be available on old distributions.
This will do the trick:
scp -o 'Host remote2' -o 'ProxyCommand ssh user#remote1 nc %h %p' \
user#remote2:path/to/file .
To SCP the file from the host remote2 directly, add the two options (Host and ProxyCommand) to your ~/.ssh/config file (see also this answer on superuser). Then you can run:
scp user#remote2:path/to/file .
from your local machine without having to think about remote1.
With openssh version 7.3 and up it is easy. Use ProxyJump option in the config file.
# Add to ~/.ssh/config
Host bastion
Hostname bastion.client.com
User userForBastion
IdentityFile ~/.ssh/bastion.pem
Host appMachine
Hostname appMachine.internal.com
User bastion
ProxyJump bastion # openssh 7.3 version new feature ProxyJump
IdentityFile ~/.ssh/appMachine.pem. #no need to copy pem file to bastion host
Commands to run to login or copy
ssh appMachine # no need to specify any tunnel.
scp helloWorld.txt appMachine:. # copy without intermediate jumphost/bastion host copy.**
ofcourse you can specify bastion Jump host using option "-J" to ssh command, if not configured in config file.
Note scp does not seems to support "-J" flag as of now. (i could not find in man pages. However above scp works with config file setting)
There is a new option in scp that add recently for exactly this same job that is very convenient, it is -3.
TL;DR For the current host that has authentication already set up in ssh config files, just do:
scp -3 remote1:file remote2:file
Your scp must be from recent versions.
All other mentioned technique requires you to set up authentication from remote1 to remote2 or vice versa, which not always is a good idea.
Argument -3 means you want to move files from two remote hosts by using current host as intermediary, and this host actually does the authentication to both remote hosts, so they don't have to have access to each other.
You just have to setup authentication in ssh config files, which is fairly easy and well documented, and then just run the command in TL;DR
The source for this answer is https://superuser.com/a/686527/713762
This configuration works nice for me:
Host jump
User username
Hostname jumphost.yourorg.intranet
Host production
User username
Hostname production.yourorg.intranet
ProxyCommand ssh -q -W %h:%p jump
Then the command
scp myfile production:~
Copies myfile to production machine.
a simpler way:
scp -o 'ProxyJump your.jump.host' /local/dir/myfile.txt remote.internal.host:/remote/dir

In Linux, How do you automatically run commands with custom parameters you feed it on SSH login?

This question:
https://superuser.com/questions/355029/linux-how-to-automatically-run-commands-on-ssh-login#355030
Only tells me how to run static commands. What it does not tell me is how I can feed it parameters. So say for example, I would like something like this to happen:
$ ssh boat#programming.com -p 2222 --parameter1 "boat programming"
Last login: Sat Dec 10 03:59:37 2016 from some place
boat programming
# .bashrc executes something like this:
echo $parameter1
If I have to use a language like expect, fine, but ideally I would like to keep this straightforward and simple.
Save this short script (on your remote system) with name run in a directory which is part of your $PATH variable (on your remote system) and make it executable.
#!/bin/bash
echo "$2"
Use it this way:
ssh boat#programming.com -p 2222 run --parameter1 "'boat programming'"
Output:
boat programming
The way, in theory, to do this is to put parameter1 in your environment, and let the remote process inherit it from ssh.
$ parameter1="boat programming" ssh boat#programming.com -p 2222
In practice, this probably will not work, because it requires the remote sshd agent to be running with the PermitUserEnvironment option enable, which is not true by default.
The only way to force this would be to run bash explicitly on the remote host with the appropriate environment.
$ ssh boat#programming.com -p 2222 'parameter1="boat programming" bash -i'
Here is my working solution:
0) If you want to automate password entry (Completely optional):
sudo apt install sshpass
1) SSH into your server, and create a file called run
#!/bin/bash
echo $parameter1
2) Make it executable
chmod +x run
3) Handle the parameters like this (Concatenate these lines.):
Avoid manual input of the password. (Be Careful!)
sshpass -p "$YOURPASSWORD"
Standard SSH login
ssh -o StrictHostKeyChecking=no boat#programming.com -p 2222
Parameters must go first. Use single quotes within double quotes otherwise day will be returned as an unknown command error:
parameter1="'happy day'"
Give an absolute path to the program you wrote.
/path/to/run
Alltogether:
sshpass -p "$YOURPASSWORD" ssh -o StrictHostKeyChecking=no boat#programming.com -p 2222 parameter1="'happy day'" /path/to/run

Bash extract user for a particular host from ssh config file

I'm writing a bash script where I need to obtain a particular user from an ssh config file. The ssh config file looks a little something like this:
HOST blag
HostName blag.net.au
Port 2683
User blaguser
Host bloo
User ABCDEF
IdentityFile ~/.ssh/id_rsa
HOST biff
HostName biff.net.au
Port 2683
User biffuser
I want to obtain the string 'ABCDEF' and put it in a variable, by searching for Host bloo.
I was able to use the answer at https://superuser.com/questions/791374/get-variable-values-from-config-file/791387#791387?newreg=6626dd5535194d0180a91b6ace31e16f to read the config file but it assigns the array with the last host entry in the file.
I'm able to delete the host entry with this answer How can I remove a Host entry from an ssh config file?. The sed command here could be edited to extract the correct User but I'm not sure precisely how
I'm having a lot of trouble with it. Can anyone assist? An answer which uses sed would be preferable.
You can use ssh configuration test mode to parse the configuration file and return you the expected value:
ssh -G hostname | grep "^user "
This should work since openssh-6.8.
Adding to #Jakuje's correct answer. This one will return only the username
$ ssh -G hostname | grep -m1 -oP "(?<=user ).*"
ubuntu
where grep parameters mean
-m1 - stop reading after first matches
-o - print only the matching part of the line
-P - use Perl compatible positive look behind regex
As per 123's comment above:
var=$(awk '/^Host bloo$/{x=1}x&&/User/{print $2;exit}' ssh.conf)
That will assign value ABCDEF to var.

using ssh keys in bash script

I've setup ssh keys form server A to server B and I can login to server B without a password. I'm trying to setup a reverse ssh tunnel in a bash script. From the command line if I do
ssh -N -R 1234:localhost:22 user#mydomain.co.uk -p 22
form server A it works as expected i.e no password required, however if I use it in a script
#!/bin/bash
/usr/bin/ssh -N -R 1234:localhost:22 user#mydomain.co.uk -p 22
I get asked for the password
user#mydomain.co.uk's password:
How do I make it so it uses the keys?
You need to let ssh know where it should search for the keys, if they are not in standard location and not passphrase protected. The easiest thing is by specifying -i switch directly to ssh:
/usr/bin/ssh -i /path/to/key -N -R 1234:localhost:22 user#mydomain.co.uk -p 22
Or cleaner way in your ~/.ssh/config like this:
Host mydomain.co.uk
IdentityFile /path/to/key
But make sure the script is run with your user context, so the script will see the configuration file.
If you have keys in standard location (~/.ssh/id_rsa), your code should work just fine. Although it should work if you have your keys stored in ssh-agent, which you can verify using ssh-add -L before starting the script. ssh-agent also solve the problem, if he keys are passphrase protected.

Can an ~/.ssh/config file use variables?

I am writing an SSH config file and want to perform a bit of logic. For example:
Host myhost1
ProxyCommand ssh -A {choose randomly between [bastion_host1] and [bastion_host2]} -W %h:%p
Is it possible to achieve the above using (bash?) variables? Thanks!
Your ProxyCommand can be a shell script.
host myhost1
ProxyCommand $HOME/bin/selecthost %h %p
And then in ~/bin/selecthost:
#!/usr/bin/env bash
hosts=(bastion1 bastion2)
onehost=${hosts[$RANDOM % ${#hosts[#]}]}
ssh -x -a -q ${2:+-W $1:$2} $onehost
Untested. Your mileage may vary. May contain nuts.
Per comments, I've also tested the following, and it works nicely:
host myhost1 myhost2
ProxyCommand bash -c 'hosts=(bastion1 bastion2); ssh -xaqW%h:22 ${hosts[$RANDOM % ${#hosts[#]}]}'
Of course, this method doesn't allow you to specify a custom port per host. You could add that to the logic of a separate shell script if your SSH config matches multiple hosts in the same host entry.
In ~/.ssh/config you cannot have much logic, and no Bash. The manual for this file is in man ssh_config, and it makes no mention of such feature.
What you can do is create a script that will have the logic you need, and make you ssh configuration call that script.
Something along the lines of:
ProxyCommand sudo /root/bin/ssh-randomly.sh [bastion_host1] [bastion_host2]
And write a Bash script /root/bin/ssh-randomly.sh to take two hostname parameters, select one of them randomly, and run the real ssh command with the appropriate parameters.
No; .ssh/config is not processed by any outside program. You'll need a shell function along the lines of
ssh () {
(( $RANDOM % 2 )) && bastion=bastion_host1 || bastion=bastion_host2
command ssh -A "$bastion" "$#"
}
This can be handled within ssh config by using a helper app. For example,
Host myhost match exec "randprog"
hostname host1
Host myhost
hostname host2
and then randprog will randomly return 1 or 0 (0 will match the first line, giving host1).

Resources