Currently when you create a drop rule with an inverse GeoIP match, it also drops the various reserved IP ranges that do not have a specific geographical region (ie. RFC1918 addresses).
Example of a rule that is supposed to block everything except for networks in Canada and US:
set firewall ipv4 name XYZ-FORWARD-IPV4 rule 10 action 'drop' set firewall ipv4 name XYZ-FORWARD-IPV4 rule 10 destination geoip country-code 'us' set firewall ipv4 name XYZ-FORWARD-IPV4 rule 10 destination geoip country-code 'ca' set firewall ipv4 name XYZ-FORWARD-IPV4 rule 10 destination geoip inverse-match
The db-ip (https://db-ip.com/) databases lumps these all into a 'zz' country code:
zcat /usr/share/vyos-geoip/dbip-country-lite.csv.gz | grep ZZ 0.0.0.0,0.255.255.255,ZZ 10.0.0.0,10.255.255.255,ZZ 100.64.0.0,100.127.255.255,ZZ 127.0.0.0,127.255.255.255,ZZ 169.254.0.0,169.254.255.255,ZZ 172.16.0.0,172.31.255.255,ZZ 192.0.0.0,192.0.0.255,ZZ 192.0.2.0,192.0.2.255,ZZ 192.88.99.0,192.88.99.255,ZZ 192.168.0.0,192.168.255.255,ZZ 198.18.0.0,198.19.255.255,ZZ 198.51.100.0,198.51.100.255,ZZ 203.0.113.0,203.0.113.255,ZZ 224.0.0.0,255.255.255.255,ZZ ::,1fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff,ZZ 2001:db8::,2001:db8:ffff:ffff:ffff:ffff:ffff:ffff,ZZ fc00::,fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff,ZZ fe80::,febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff,ZZ
In my opinion this is incorrect behaviour as these IPs do not necessarily exist in any specific country. I am curious to know what the preferred way to get around this is? Default to adding the 'zz' addresses when an inverse-match rule exists? Or add 'zz' as an option to be specified in rules?
This patch will automatically add country code 'zz' to any rule with inverse-match defined:
$ diff -rupP /usr/lib/python3/dist-packages/vyos/firewall.py.orig /usr/lib/python3/dist-packages/vyos/firewall.py --- /usr/lib/python3/dist-packages/vyos/firewall.py.orig 2023-11-21 16:01:02.557535168 +0000 +++ /usr/lib/python3/dist-packages/vyos/firewall.py 2023-11-21 19:32:23.892547815 +0000 @@ -584,6 +584,10 @@ def geoip_update(firewall, force=False): # Map country codes to set names for codes, path in dict_search_recursive(firewall, 'country_code'): + # If inverse-match is set, add country zz (reserved IPs) + # as they don't belong to a specific country. + if dict_search_args(firewall, *(path[:-1] + ['inverse_match'])) != None: + codes.append('zz') set_name = f'GEOIP_CC_{path[1]}_{path[2]}_{path[4]}' if ( path[0] == 'ipv4'): for code in codes: