So I have this beast of a windows program called XenCenter that is fairly necessary for administering a Citrix XenServer. It connects to port 443 on the Xen host, which is not normally exposed with a public IP. And I do not have a working VPN to this machine. Once again, SSH to the rescue:
ssh -t -L *:443:localhost:11111 user@hostname1 ssh -L *:11111:localhost:443 user@hostname2
This is the most general case, and can be chained through more then two hosts. Note that the hostname or IP address between the two port specs is always relative to the remote host. Which is to say, the first localhost is on hostname1, and the second is on hostname2. Also note that user@hostname can be replaced with a locally defined Host from ~/.ssh/config, and can include the full array of ssh options like -p and -i. And finally, the *: allows connections from anywhere, not just localhost. The first one is obviously necessary because I am running this SSH on my Linux desktop, and then connecting to it with XenCenter from a Windows VM. (Not sure why the second *: is necessary....)
Because 443/https traffic is already encrypted, the above can be simplified with little loss of security:
ssh -L *:443:hostname2:443 user@hostname1Which is to say, hostname1 will forward traffic directly to port 443 on hostname2, assuming no firewalls intervene.
(Well, at least two hops is reliably working for me....)
A common headache, particularly for those of us who live in China: the necessity of ssh'ing first into an intermediate machine, thence to the final destination machine. Even with SSH keys, this gets ugly to setup, and uglier to maintain in the face of frequent disconnections. Unless we can find a way to login from destop through intermediate machine to destination machine, all in one entirely passwordless step.
The secret is to leverage SSH agent. First add AT LEAST any keys you will need after the first hop to your local desktop ssh agent, ie.
ssh-add /home/myuser/clients/clientname/id_rsaThen chain two or more ssh logins together as follows:
autossh -A -t firstname.lastname@example.org ssh email@example.com
(In this case, the 10.130.2.78 is on a private network behind a router without a public IP. intermediate-server.com is on the same private network, with a public IP.)
autossh will automatically reconnect an disconnected SSH session. (Works best with login via SSH key.)
-A forwards your desktop SSH agent through the first hop to the second hop.
-t forces pseudo-tty allocation
All hops before the destination need both -A and -t.
In my ~/.bashrc I put this:
alias ssh-tszz1="ssh-add /home/myuser/clients/clientname/id_rsa && autossh -A -t firstname.lastname@example.org ssh email@example.com"
so that I can login to firstname.lastname@example.org in any terminal, by simply invoking:
It would be more elegant to have everything configured in ~/.ssh/config, perhaps with the ProxyCommand directive and nc, but so far no success with this.
Note that I have found the second ssh fails for some reason if there is a port number, which I found an extra pair of quotes to fix. Ie. the above, with port number 1212 added, becomes:
alias ssh-tszz1="ssh-add /home/myuser/clients/clientname/id_rsa && autossh -A -t email@example.com 'ssh -p 1212 firstname.lastname@example.org'"
To add a third SSH hop:
alias ssh-tszz1="ssh-add /home/myuser/clients/clientname/id_rsa && autossh -A -t email@example.com 'ssh -A -t firstname.lastname@example.org ssh email@example.com'"
Note the second use of the "-A -t" switches, on the second ssh hop. Of course, one can make succeeding hops simpler by populating the .ssh/config file on intermediate servers, and using a alias Host from .ssh/config instead of fully specifying the ssh parameters in the original invocation, as I am doing here.
How to use SSH keys to login to your server without giving a password -- perhaps contra-inuitively, this kind of passwordless login is usually more, not less, secure then a password login. (Not to mention convenient and time-efficient....)
Say we want to login to server.com from our desktop without a password. The rdiff-backup wiki provides a somewhat obtuse and hard-to-read article on the subject. For the basics, I prefer to start with this article.
On your desktop, run:
ssh-keygen -b 4096 -t rsa -f /home/username/.ssh/id_rsa
Do not enter a pass-phrase!! Leave it blank
(Note: we are creating a 4096 bit key here as recommended by nearlyfreespeech.net. It is possible that some situations will require a 1024 bit key, and this key will not be useable in that situation. It is possible to have multiple keys, which may be invoked by the "ssh -i" option, for instance.)
Now copy the public key "id_rsa.pub" to firstname.lastname@example.org:
scp /home/username/.ssh/id_rsa.pub email@example.com:
Go to server.com and append the new key to the authorized_keys:
cat ../id_rsa.pub >> authorized_keys
Restrict access to these keys on both your desktop and your root@server:
chmod -R go-rwx ~/.ssh
Test to verify you are not prompted for a password. In a terminal on your desktop, try a verbose ssh to server.com:
ssh -v firstname.lastname@example.org
If there are problems and you are prompted for a password (you should not be) the -v output should give you some clues.
In some situations, one can make SSH key logins even more secure. For instance, on server.com, add some security directives to a particular key in /root/.ssh/authorized_keys by pre-pending the following:
command="rdiff-backup --server --restrict-read-only/",no-port-forwarding,no-X11-forwarding,no-ptyie. in /root/.ssh/authorized_keys the key in qestion now contains the following, ALL ON ONE LINE, and note the single space before "ssh-rsa":
command="rdiff-backup --server --restrict-read-only /",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AA ... uqdswe= user@desktop
"no-pty" explicitly forbids terminal priveleges. "command" here restricts the session to running one and only one command: "rdiff-backup --server --restrict-read-only".
Now if you try to ssh to email@example.com from a terminal, your terminal will just lock-up and stop responding. If you really do want to allow this (a terminal ssh to firstname.lastname@example.org without a password) just remove the "command" and "no-pty" directives from the server.com /root/.ssh/authorized_keys file.
Note that this will only work from the account "username" on your desktop machine where you have generated a /home/username/.ssh/id_rsa file and then passed the public key to server.com. Trying to ssh from any other desktop account to email@example.com will result in a password prompt.
You can re-use existing SSH connections by adding this to ~/.ssh/config file:
Thereafter, after you login and open a connection to an SSH server, if you open another connection from another terminal, it will re-use the first connection. No need to login again, no need to wait for the connection to be re-negotiated. Over a slow, long-distance SSH connection, this can slow the wait time from tens of seconds to two seconds. This applies to SCP transfers as well. Much saved time.
If you have a long list of servers you log into regularly, particularly on non-standard ports, these connections can also be aliased in the ~/.ssh/config file:
Thereafter, "ssh my-chosen-alias" will connect to firstname.lastname@example.org on port 10122. Unfortunately SCP does not seem to respect these aliases, or at least I have not found out how to make that work. But this is a way, for instance, to transparently get backuppc to connect to a backup client using a non-standard port.Host my-chosen-alias Hostname server.com IdentityFile /path/to/id_rsa User root Port 10122
I cannot believe I put up with this for so long: in the past when I connected to servers outside China, the SSH session would consistently disconnect after the terminal had been idle for only a very few minutes. This was very consistent, far more then "every once in a while". (I am guessing there was some Great FireWall-related foul play involved....)
Thanks to Donncha I have an elegant one-line solution by adding the following to /etc/ssh/ssh_config:
ServerAliveInterval 60This causes my ssh client to send a "keep alive" message to the server after 60 seconds of inactivity. Only if the server fails to respond is the connection broken. Even in China, this seems to be quite efficient at keeping my international ssh connections open for hours at a time.
If you find yourself doing exactly the same set of steps on more then one machine, then Cluster SSH is an option. Its very simple to get started. In ~/.csshrc define the set(s) of workstations that you would like to control:
clusters = = host1 host2 host3 = user@host4 user@host5 host6 =
Then execute "cssh tag1" and three terminals, one each for tag1, tag2, and tag3 will appear, plus the cssh control window. Any text typed into the control window will be echoed in all terminals.
If passwordless authentication has not been configured for the remote boxes, then you will have to enter a password in each terminal at the start.