9

I've setup ssh and router port forwarding so I can ssh into a computer on my home network when I'm not at home. Currently I have two entries in my .ssh/config file one for when I'm on my home network and one for when I'm not:

Host mycomputer
  HostName 192.168.X.X

Host mycomputerathome
  HostName my.no-ip.dynamic

This works but I'm wondering if I can make things easier on myself. I was hoping there's a way to list multiple HostName entries such that if the first fails it falls back to the second:

Host mycomputer
  HostName 192.168.X.X
  HostName my.no-ip.dynamic

So that it will first try to connect to a host on my local network and if that isn't present, it'll try to connect using my no-ip dynamic host name. I have tried entering two HostNames but running ssh mycomputer just blocks doing nothing.

I've turned off password authentication in favor of keys so accidentally connecting to a computer on the local network when I'm not on my home network shouldn't risk my password going anywhere it shouldn't.

Is it possible to specify fallback HostNames to try if the first one doesn't work?

8

It's ugly, but I think you could do it using the exec criterion to Match on the exit status of a port knock e.g.

Host mycomputer
  Match exec "nc -z 192.168.1.11 %p"
    HostName 192.168.1.11
  Match !exec "nc -z 192.168.1.11 %p"
    HostName my.no-ip.dynamic

Note that this can't really tell whether you're on "your" home network - just that you're on a private LAN segment with the same address range that happens to have a service listening on the same address/port.

  • 1
    I did have to add a -w 1 or else nc seemed to wait forever. What could be simpler is the second Match can Match exec "true" because if the first match failed, just blindly try the second choice. – Corey Ogburn Jul 11 '18 at 18:36
  • @CoreyOgburn ah yes I was trying to think of a nicer way to do the alternate condition (pity Match doesn't have an Else) – steeldriver Jul 11 '18 at 18:38
  • So I ran into an issue with this approach. I also run a site, say xyz.com, and when I tried to ssh xyz.com my Match exec "true" caught that and redirected me into my home server using my remote HostName. I will try with your exec but I think the same thing will happen. – Corey Ogburn Jul 16 '18 at 18:01
  • Yeah, using your Match exec... Match !exec is causing ssh'ing to other domains to trigger the Match !exec and rewrite the HostName. – Corey Ogburn Jul 16 '18 at 18:42
  • 2
    So it turns out that ~/.ssh/config couldn't care less about indentation. Certain commands reset the scope, i.e. each new Host line says "previous lines were for the previous Host, the following lines are for this new Host." Turns out Match has the same "scope resetting" power as Host. To account for this, I replaced my Host line with Match Host mycomputer exec "nc -w 1 -z 192.168.X.X 22" and defined all the custom values for my local network. I then added a matching line except !exec and added all the values for when I'm off network. Now it works fine for all hosts. – Corey Ogburn Jul 16 '18 at 21:21
2

I'm using like this.

Match host mycomputer exec "nc -G 1 -z 192.168.1.11 %p"
    HostName 192.168.1.11
Match host mycomputer # fallback
    HostName my.no-ip.dynamic
Host mycomputer
    # ... other configs

Host not-my-computer
# ... other configs

ssh_config doesn't have something like indentation block. If you want to limit match sentence to a specific host, then you should describe the full condition.

You can avoid long awaiting nc by giving it -G 1 (connection timeout 1s) option, and you can utilize following behaviour to avoid multiple invocation of nc

Match
Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another Match line or the end of the file. If a keyword appears in multiple Match blocks that are satisfied, only the first instance of the keyword is applied.

https://www.freebsd.org/cgi/man.cgi?sshd_config(5)

1

No; if you specify multiple HostNames for one Host entry, only the first will be acknowledged:

$ grep -A5 Host .ssh/config
Host test
   HostName fake.tld.xyzzy
   HostName real.example.com
   HostName 127.1.2.3
   User username
$ ssh test
ssh: Could not resolve hostname fake.tld.xyzzy: Name or service not known
  • I guess it makes sense. If I type in ssh mycomputer it should be pretty unambiguous which computer I'm connecting to. – Corey Ogburn Jul 11 '18 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.