37

I'm looking for a way to use specific CIDR blocks to match hosts in the SSH client configuration (usually ~/.ssh/config). For example, I have an entry to forward all traffic through a bastion host if the IP falls into a certain range, let's say 10.1.0.0/16:

host 10.1.*
    proxycommand ssh -q bastion -W %h:%p

This works very well, but how about when I add some ranges that don't fit the dot notation exactly?

# doesn't work, unfortunately
host 10.2.0.0/18
    proxycommand ssh -q bastion-foo -W %h:%p
host 10.2.64.0/18
    proxycommand ssh -q bastion-bar -W %h:%p

Is there something in the manual that I've missed, or a clever scripting trick that would enable matching these host IP ranges?

fazy
  • 770
  • 3
  • 8
  • 13

3 Answers3

35

Matching against patterns in the ssh_config file is done as basic pattern matching, not as a network/CIDR matching. So using CIDR notation is not going to work.

The man page explains that:

A pattern consists of zero or more non-whitespace characters, * (a wildcard that matches zero or more characters), or ? (a wildcard that matches exactly one character).

The best you can do is to use a list of more than one pattern. Again, from the manual page:

A pattern-list is a comma-separated list of patterns. Patterns within pattern-lists may be negated by preceding them with an exclamation mark (!).

So to cover your two /18 nets, you'd need to list:

  • all hosts matching 10.2.?.* (i.e. 10.2.0.0–10.2.9.255)
  • all hosts matching 10.2.??.* (i.e. 10.2.10.0–10.2.99.255)
  • all hosts matching 10.2.10?.* (i.e. 10.2.100.0–10.2.109.255)
  • all hosts matching 10.2.11?.* (i.e. 10.2.110.0–10.2.119.255)
  • all hosts matching 10.2.12?.* EXCEPT the ones matching 10.2.128.* and 10.12.129.* (and remember that the exclusion must come first!)

Your pattern list should then look like this:

Host "10.2.?.*","10.2.??.*", "10.2.10?.*","10.2.11?.*","!10.2.128.*","!10.2.129.*","10.2.12?.*"
Jenny D
  • 27,780
  • 21
  • 75
  • 114
  • 7
    To be precise, this is not a regular expression, it's a globbing wildcard. – Gabor Garami Sep 19 '16 at 11:56
  • 3
    Thanks for the answer, it nearly works for me but I actually needed to differentiate those two ranges with separate `host` entries. It also needed each one quoted separately (ssh/Mac). Shortest I could find: `host "10.2.?.*", "10.2.??.*", "!10.2.64*", "!10.2.65*", "!10.2.66*", "!10.2.67*", "!10.2.68*", "!10.2.69*", "!10.2.7*", "!10.2.8*", "!10.2.9*"` and `host "10.2.??.*", "10.2.10?.*", "10.2.11?.*", "10.2.12?.*", "!10.2.1?.*", "!10.2.2?.*", "!10.2.3?.*", "!10.2.4?.*", "!10.2.5?.*", "!10.2.60.*", "!10.2.61.*", "!10.2.62.*", "!10.2.63.*", "!10.2.128.*", "!10.2.129.*"` – fazy May 12 '17 at 17:16
8

You could use the very powerful Match directive with the grepcidr tool:

Match exec "grepcidr 10.2.0.0/18 <(echo %h) &>/dev/null"
   Proxycommand ssh -q bastion-foo -W %h:%p

How this works:

  • %h in the commandline gets expanded to the hostname (see Tokens)
  • <(echo %h) wraps this into a temporary "file"
  • Maybe use <(dig +short %h) if working with hostnames
  • then use grepcidr to match the hostname %h against a.b.c.d/e
  • &>/dev/null because we only care about the return code, not the output.

This needs the additional tiny grepcidr package, which should exist in your package manager.

Alex Stragies
  • 409
  • 4
  • 12
3

Keep an eye on http://bugzilla.mindrot.org/show_bug.cgi?id=1169 which may eventually provide a mechanism for this.

Shannon
  • 131
  • 1
  • last comment 2014 ⌚⌚ – nhed Sep 26 '19 at 16:45
  • OpenSSH developer [Damien Miller](https://twitter.com/damienmiller) recently responded to [my asking this on twitter](https://twitter.com/adamhotep/status/1337187110990696450) by saying “I think we're more likely to turn off `CheckHostIP` (the thing that spams addresses into known_hosts) in the short term, as nobody has satisfactorily explained what problem it solves to me. CIDR in ssh_config probably is less likely, as there are too many chicken and egg problems in config parsing vs address resolution.” – Adam Katz Dec 14 '20 at 03:23
  • Link only answer. :( – Konrad Gajewski Feb 04 '21 at 00:45