SSH: Conditional host address based on network or location

I have been searching extensively to find a solution to ease management and administration of my servers from multiple location. Let me present my environment and then my use cases


  • Site One (\24)
    • Server A
    • Server B
    • Server C
  • Site Two (\24)
    • Server D
    • Server E
  • Site Three (\24)
    • Server F

Use cases

I manage these servers from any of the sites and even other external networks and the two main issues I have had are

  1. Reaching any server from any other server, workstation or laptop in the field with:
    ssh server-x
  2. Be able to bridge multiple server jumps. Normally, only “A”, “D” and “F” have an externally port forwarded to it.
    For example, sending a file from “B” to “E” is troublesome with

    rsync local_file server-e:.

My solution

Perhaps my Google skills are lacking, but finding a solution that is efficient across all locations and dynamic was hard. There were quite a few samples of having two settings in the ssh config file for each host, i.e. server-x-local and server-x-remote. Sure, doable but a pain to maintain across all sites and not transparent enough.

The solution to this problem was the Match keyword for the ssh config. This is the configuration for Server A:

Match Originalhost server-a Exec "ifconfig | grep 10.0.1"
Host server-a

Let’s explain this construct. The match clause executes the ifconfig and pipes the output to grep in order to see if we are on this subnet. This will evaluate to true if I’m located on any host on subnet One. If the match is true it will set the hostname to the local IP of the server. If the clause evaluates to false, the default (external DNS) hostname of the server will be used. According to the ssh_config man page, the first match of a setting will be used. Therefor, the Match clause needs to be before the Host.

This works great from my initial testing and makes it possible to use the very same ssh config file regardless of client.

The second issue: Jump/Proxy/Bastion setup.

In order to reach other servers behind the externally connected servers easily I had previously been using SSH tunneling to solve some tricky cases. Now that I had some Google flow I attempted to take a stab at that challenge as well.

As it turns out, this was an easier fix thanks to the ProxyCommand feature in later SSH versions. From my understanding, this executes a custom command as a precondition to the final SSH connection.

Expanding on the previous solution, this is what I came up with. First, the complete Server A ssh configuration, same as before.

Match Originalhost server-a Exec "ifconfig | grep 10.0.1"
Host server-a 

Then, the Server B configuration:

Match Originalhost server-b Exec "ifconfig | grep 10.0.1"
     ProxyCommand none
Host server-b
     ProxyCommand ssh -W %h:%p server-a

The idea here is the same. The default case is connecting from an external site and the ProxyCommand initiates an ssh connection to server-a first and uses it as a proxy to then connect to server-b. If, on the other hand, we are located on the local subnet already, the ProxyCommand is disabled and no proxy connection to server-a is made.

All that remains now is to configure all different hosts at one client and the roll out the very same config file to any host that is going to connect to any of the servers.


I’m really happy with this solution and it has greatly improved my efficiency when connecting to the different servers. Now the connections are really transparent and flexible!

Let me know if you have any success with this solution!



5 thoughts on “SSH: Conditional host address based on network or location

  1. Thanks for the detailed writeup. I just need to get to my home servers when I’m traveling, and this is great solution. I use iTerm with Profiles, and this way, I don’t have to have duplicate profiles set up. Very clean.

  2. I have done something similar in the past but for a different reason. When I want to access my home server I’m either at home, or not. If I’m at home I have to use my local IP, this is because my home router does not support NAT Loopback ( By using the same method you have above, but with a different cmd, I’m able to detect if I’m on my home network. (IP addresses changed for example)
    Match OriginalHost server-a Exec “curl -s ‘’ | grep ‘’”
    Host server-a
    I went with this solution because many home routers use the same subnet so simply checking if I’m on “” wouldn’t work as I’d get too many false positives.

  3. THANKS!

    I love this solution. I found it more useful for my setup to check WIFI hotspot name in the condition using nmcli command.

    Match host some-host Exec “nmcli -g NAME connection show –active | grep accelico”

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.