Using ProxyCommand with OpenSSH and a Bastion server.

So at work we have to use a bastion host for all our connections to servers to be able to get called PCI compliant. This kind of stuff could be a pain to use when you have to use another host to do RSYNC/SCP or other stuff that need direct transfer to workstation.

Thankfully OpenSSH is very flexible and have multiple options to easy the pain. If you add this to your ~/.ssh/config :

Host bastion
ProxyCommand none
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p

Host *
ProxyCommand ssh -qax bastion ‘nc -w 600 %h %p’

This will allow you to pass all SSH requests to the bastion server.

I have experimented with different options and this seems to be most efficient way. The ControlMaster ControlPath is to speed up the connections by not reopening a tcp socket all the time to the bastion server. This seems to cause problems with the OpenSSH version shipped with some distros (ie: Fedora) so you may want to remove it if you experience problems. For the ProxyCommand there is way to use cat like this :

ProxyCommand ssh bastion ‘exec 3<>/dev/tcp/%h/22;(cat <&3 & );cat >&3’

but the cat processes seems to hang in memory on the bastion server so netcat seems a better option.  I heard that tcpconnect from the tcputils package should make things smoother but I haven’t tried that.

I have other options in my SSH configuration to allow to be less verbose see ssh_config(5) manpage for detailed description of each of these options :

Host *
ForwardAgent yes
GSSAPIAuthentication no
VerifyHostKeyDNS no
StrictHostKeyChecking no
HashKnownHosts no
TCPKeepAlive yes
ServerAliveInterval 600

By the way forgot to mention you would need to have SSH key exchange configured with the bastion server with a SSH agent runing (these days all distros should do that by default) to don’t have to type the password of your username on bastion server.

I have heard there is way to do that on Windows with putty and plink but I haven’t tried that see this post here about it.

5 thoughts on “Using ProxyCommand with OpenSSH and a Bastion server.”

  1. Awesome solution we have searched all over the net, tried iptables galore but this is, by far, the best and easiest to use.

    Now we the security of ssh keys on top of locking down the remote servers to one central location which gives us much greater security and control.

    Thanks for your post.

    Matt Ayers

  2. Using “ProxyCommand ssh -W %h:%p ssh bastion” should also work with appropriate client/server versions, without the need for nc, however I’ve seen issues with the connection attempts if ControlMaster/ControlPath/ControlPersist are also configured (invalid ssh packet length) UNLESS you first open the persistent connection to the bastion host (“ssh -fN bastion”, will open a connection to the bastion, but with no command line associated with it, Control[Master/Path/Persist] will allow that to be used with future ssh sessions up to the timeout specified in the ControlPersist option).

    Another option is “DynamicForward ” in the bastion host definition and “ProxyCommand nc -X 5 -x localhost: %h %p” in the wildcard host definition. This relies on nc on the local system rather than on the bastion.

    1. tks david! This article was written a long time ago and I don’t think DynamicForward did exist at that time!

Comments are closed.