SSH config and OSX locations

My home network is set up with a bastion host; if you want to ssh in from outside you go to an obscure port on my router, giles.example.com which is forwarded to a specific internal system, bastion. From there you can ssh in to other systems on the network such as workstation. A fairly simple setup which has the advantage of giving me a single point of ingress so it’s easier to keep my security and monitoring up to date. Unfortunately it makes it a pain the neck to actually connect to the internal systems. But that’s what the ssh config file on my laptop is for:

Host bastion
     hostname=giles.example.com
     Port=6666

Host workstation
     ProxyCommand=ssh -W %h:%p 
     hostname 192.168.1.2

Now from outside the network, ssh workstation will create an ssh session, proxied by bastion, to the workstation system behind my home router.

That’s great, but the configuration file is on my laptop — something that gets moved around. I really don’t want to go through the bastion host when I’m sitting at home, not least because my firewall won’t allow me to connect to my public FQDN from inside: giles.example.com is only intended to be accessed from outside. So I want to use different config files depending on my location. And I don’t want to have to change that file manually – this was all about removing the inconvenience of having to log in to one host then another; simply changing that inconvenience is not a great advance.

My laptop runs OSX so I had to look around for ways of notifying a network change and then acting on it. For my purposes, being at home can be defined as being able to see the SSID of my home wifi network. We could detect this in a login script but Apple are heavily deprecating this approach so that sounds like a bad idea. More Apple friendly is to use launchd to install an agent watching for changes in SSID that the wifio interface is connected to. That’s the basis of wifi-location-changer which sets your OSX location using scselect to match the SSID you’re connected to if there is a location of that name. I’ve forked this and modified the script to generate an ssh config file based on the new location name:

if [ "x$NEW_LOCATION" != "x" -a "x$NEW_LOCATION" != "x$CURRENT_LOCATION" ]; then
    echo "Changing to $NEW_LOCATION"
    scselect "$NEW_LOCATION"

    # if ssh config is available, geneerate the location specific variant.
    if [ -d $HOME/.ssh ];
    then
        print "# Generated file: do not edit" > $HOME/.ssh/config

        if [ -f $HOME/.ssh/config.$NEW_LOCATION ];
        then
            > $HOME/.ssh/config
        fi

        if [ -f $HOME/.ssh/config.common ];
        then
            > $HOME/.ssh/config
        fi
    fi
fi

So now whenever my laptop finds itself in a new location it will regenerate its ssh config file from a common and location specific portion.