You can jump host using ProxyCommand. Some times you can only access a remote server via ssh by first login into an intermediary server (or firewall/jump host). So you first login into to the intermediary server and then ssh to another server. You need to authenticate twice and the chain can be long and is not limited to just two hosts.
Sample setup
+-------+ +----------+ +-----------+
| Laptop| <---> | Jumphost | <--> | FooServer |
+-------+ +----------+ +-----------+
OR
+-------+ +----------+ +-----------+
| Laptop| <---> | Firewall | <--> | FooServer |
+-------+ +----------+ +-----------+
192.168.1.5 121.1.2.3 10.10.29.68
I can can only access a remote server named ‘FooServer’ via ssh by first login into an intermediary server called ‘Jumphost’. First, login to Jumphost:
$ ssh vivek@Jumphost
Next, I must ssh through the intermediary system as follows:
$ ssh vivek@FooServer
Passing through a gateway or two
Instead of typing two ssh command, I can type the following all-in-one command. This is useful for connecting to FooServer via firewall called ‘Jumphost’ as the jump host:
$ ssh -tt Jumphost ssh -tt FooServer
$ ssh -tt vivek@Jumphost ssh -tt vivek@FooServer
$ ssh -tt vivek@Jumphost ssh -tt vivek@FooServer command1 arg1 arg2
$ ssh -tt vivek@Jumphost ssh -tt vivek@FooServer htop
$ ssh -tt vivek@Jumphost ssh -tt vivek@FooServer screen -dR
Where,
- The -t option passed to the ssh command force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine. Multiple -tt options force tty allocation, even if ssh has no local tty.
Say hello to the ProxyCommand
The syntax is:
$ ssh -o ProxyCommand='ssh firewall nc remote_server1 22' remote_server1
$ ssh -o ProxyCommand='ssh vivek@Jumphost nc FooServer 22' vivek@FooServer
##########################################
## -t option is needed to run commands ###
##########################################
$ ssh -t -o ProxyCommand='ssh vivek@Jumphost nc FooServer 22' vivek@FooServer htop
The netcat (nc) command is needed to set and establish a TCP pipe between Jumphost (or firewall) and FooServer. Now, my laptop (local system) is connected to Jumphost it now connected FooServer. In this example, the utility netcat (nc) is for reading and writing network connections directly. It can be used to pass connections to a 2nd server such as FooServer.
Update ~/.ssh/config file
Edit the $HOME/.ssh/config file using a text editor such as vi, enter:
$ vi ~/.ssh/config
Append the following configuration:
Host fooserver HostName FooServer User vivek ProxyCommand ssh vivek@Jumphost nc %h %p |
Save and close the file. Where,
- Host fooserver : Set nickname of your choice.
- HostName FooServer : Set the real remote server/host name.
- User vivek : Set the real user name for remote server/host.
- ProxyCommand ssh vivek@Jumphost nc %h %p : Specifies the command to use to connect to the server. In this example, I’m using nc command. Any occurrence of %h will be substituted by the host name to connect, %p by the port, and %r by the remote user name.
To test enter:
$ ssh fooserver
To see the details, pass the -v option to the ssh command. Here is another snippet:
Host server1
HostName v.server1
User root
Port 22
ProxyCommand ssh root@v.backup2 nc %h %p %r |
Now, run:
$ ssh -v server1
Sample outputs:
OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011 debug1: Reading configuration data /Users/veryv/.ssh/config debug1: /Users/veryv/.ssh/config line 1: Applying options for server1 debug1: Reading configuration data /etc/ssh_config debug1: /etc/ssh_config line 20: Applying options for * debug1: /etc/ssh_config line 102: Applying options for * debug1: Executing proxy command: exec ssh root@v.backup2 nc v.server1 22 root debug1: permanently_drop_suid: 501 debug1: identity file /Users/veryv/.ssh/id_rsa type 1 debug1: identity file /Users/veryv/.ssh/id_rsa-cert type -1 debug1: identity file /Users/veryv/.ssh/id_dsa type -1 debug1: identity file /Users/veryv/.ssh/id_dsa-cert type -1 debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.2 debug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 debug1: match: OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 pat OpenSSH* debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5-etm@openssh.com none debug1: kex: client->server aes128-ctr hmac-md5-etm@openssh.com none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Server host key: RSA d2:07:84:79:21:a7:84:84:14:ef:f1:7a:84:a5:a1:7s debug1: Host 'v.server1' is known and matches the RSA host key. debug1: Found key in /Users/veryv/.ssh/known_hosts:37 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: Roaming not allowed by server debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,password,keyboard-interactive debug1: Next authentication method: publickey debug1: Offering RSA public key: /Users/veryv/.ssh/id_rsa debug1: Server accepts key: pkalg ssh-rsa blen 279 debug1: Authentication succeeded (publickey). Authenticated to v.server1 (via proxy). debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: Sending environment. Welcome to Ubuntu 14.04.2 LTS (GNU/Linux 3.13.0-52-generic x86_64) * Documentation: https://help.ubuntu.com/ Last login: Sun May 17 15:41:26 2015 from 10.70.203.66
The sftp syntax
The syntax is as follows:
sftp -o 'ProxyCommand=ssh %h nc firewall.nixcraft.net.in 22' \ -o 'HostKeyAlias=firewall.nixcraft.net.in' \ vivek@server1.nixcraft.net.in |
See man pages for more info: ssh(1),ssh_config(5),nc(1)



11 comment
Hi,
Thanks a lot…
Nice article
Good article Vivek.
If you liked this and want to see how to take it to the next level, take a look at my Empowering OpenSSH article
I use this technique to reach hundreds of servers 2 or 3 or 4 jumps deep in my clients network. It works like a champ.
just a note, you can use -W instead running nc
ProxyCommand ssh gateway -W %h:%p
I don’t have `nc` on the jumpbox, so this worked better. Thanks :)
Why are you using fooserver in your example?? Is that server 1, server 2, a server at a Chinese food restaurant?? Just use common sense terms (server 1, server 2, local computer, etc.) so that people can understand what you are trying to say.
Please stop the Foo pollution!! Dumbest thing Linux people do.
Actually the fooserver is great. Instantly you can look at it and know it is totally a placeholder and needs to be replaced by a different server. server1 or server2 can be a lot more misleading. Is that the server you were talking about in the previous paragraph? Some global scope, some listed arguments to a function, etc. Foo, bar, baz, etc are standard practice for exactly this reason:
http://www.quora.com/What-does-foo-mean-in-computer-science
http://english.stackexchange.com/questions/27843/what-does-foo-mean
http://en.wikipedia.org/wiki/Metasyntactic_variable
I agree with the use of FOO(server).. At first I wasn’t sure and had to look twice. Caught on finaly (my bad?). SERVER1, SERVER2 etc would allow more folk to understand IMHO (My Humble Opinion:). Thanks for the info however..
To all the people complaining about the use of Foo: Please go read up on unix hacker culture. There is a rich history behind the chosen meta-syntactic variables in this example. The way I see if, if you are trying to learn SSH before FOO you need to take a step back and read a few dusty books. Show some respect for those who came before you (and provided all this great free software).
I don’t know about what hacker culture you’re talking about. And not sure if I really care about it. I am an exclusive UNIX user/sysop/dev since 1994 and always find foo bar bah behehe annoying and more like today’s pseudo-language of lol, rofl, etc, that only shows lack of imagination and shallowness, the same over-confident mindset that gave birth to RTFM partly from inability to verbalize one’s supposed knowledge, partly, and mostly, from the lack of it.
I bet you’re a perl guy, just because its gibberish syntax makes you feel special.
Since only 1994? Get off my lawn!
Great article however you should be using ‘ssh -W’ instead of ‘ssh … nc’ for the “hop” command.