Automatic SSH Proxy Selection

2016-02-08

A common network configuration is to utilize a VPN which allows the users to connect to internal servers providing services such as SSH. Additionally, some networks may offer external access (i.e., from outside the VPN) to a jumpbox from which internal servers can be reached.

A suitable SSH configuration file allows you to seamlessly connect to an interval SSH service. The idea is to check whether the user issuing the ssh command is connected to the VPN and then to either directly connect to the internal SSH server if possible or use the jumpbox as a proxy if necessary.

Let us assume that the host name of the internal SSH server is internal.example.com and that the host name of the jumpbox is external.example.com. The following SSH configuration (can be placed in the user's home directory under .ssh/config) executes the netcat (nc) command under the user's shell to check whether a TCP connection the internal SSH server can be established. If that is the case, the netcat command returns a zero exit status and the SSH client will set ProxyCommand to none meaning that SSH will use no proxy and connect directly to internal SSH server. In case the netcat command returns a non-zero exit status indicating failure, the condition of the Match is not satisfied and the SSH client looks for the next applicable Host or Match entry without setting the proxy setting. Note that the SSH client proceeds from top to bottom when parsing the configuration file (see ssh_config(5)). The client sets all parameters such as ProxyCommand when they appear the first time and ignores subsequent parameter values it encounters further down in the configuration file.

Match host internal.example.com exec "nc -z -w 2 internal.example.com 22"
  ProxyCommand none

Host internal.example.com
  User myinternaluser
  Port 22
  IdentityFile ~/.ssh/id_ed25519
  ProxyCommand ssh -W %h:%p external.example.com

Now, if the user issues the command ssh internal.example.com and the user is in the VPN so that the netcat command succeeds, SSH sets ProxyCommand to none but still applies all settings under the Host directive except for the ProxyCommand setting. Instead of using netcat, it is possible to use, e.g., ping -c 1 -W 2 internal.example.com to check whether internal.example.com responds to an ICMP echo request, assuming that a received ICMP echo response suggests that the user is able to connect to the internal SSH server without a proxy. The netcat and ping commands use a timeout of two seconds which can be modified to a more suitable value for the network at hand.