SSH Client Fun – Local and Global IP with a Single Hostname

I have an SSH gateway at home that I would like to access directly while I’m at home, and over NAT and a public IP otherwise. The easiest and most convenient way to do this is to have a home network connection that has a public IP and a NAT router that notices that a server with a public domain name is local and redirects traffic to that host locally. If you are unfortunate and have to use a home router that can’t do this (i.e. cheap plastic trash), another option is to set-up your own DNS server and answer DNS requests for servers you have at home from there. A bit complicated to set up, so this solution is not everybody’s darling. If this local/public conundrum only concerns SSH, there is a nifty third way: Let the ssh client check whether to use a local IP address when you are at home, or query a DNS server for the public IP address when you are outside.

And here’s my setup in my .ssh/config file for my SSH gateway server (ext-home) at home:

# Use local IP when at home
Match host ext-home exec "ip addr show | grep -q 'inet 192.168.77.'"
HostName 192.168.77.239

# Use public IP when outside and define all other required parameters

Host ext-home
Port 32924
User martin
# The hostname below is used IN CASE there was no override from the
# "match host" commands above!

HostName gw.mydomain.com

Might look a bit strange at first but it’s actually quite straight forward. Let’s look at the second part of the snippet above first: This part represents an ssh server that is reachable via a DNS name.

So far, so good, let’s go back to the beginning of the snipped: The ‘Match host‘ statement tells the ssh client to execute the ‘ip addr’ command in combination with ‘grep’ to find out if there is any network interface with an IP address in the 192.168.77.x subnet. If so, the ‘exec’ command returns true and the local IP address of the SSH server is used for the SSH HostName parameter. This overrules the HostName parameter at the end of the snippet. Not quite logical, as one would perhaps assume the last definition of a parameter is taken. However, this is not the case here. In other words, the order of the statements matter!