How can I match a CIDR range for an SSH config host entry?
Solution 1:
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 matching10.2.128.*
and10.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?.*"
Solution 2:
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.