rpthms / nft-geo-filter

Allow/deny traffic in nftables using country specific IP blocks
MIT License
97 stars 24 forks source link

Allow mode exceptions blocks traffic from private subnets #4

Closed peter-sc closed 4 years ago

peter-sc commented 4 years ago

Hello, I installed the latest script today on a Debian 10.5. My aim was to allow incoming traffic to local webserver only from Austria.

/usr/local/bin/nft-geo-filter/nft-geo-filter --table-family netdev --table-name AT-filter --interface enp1s0 --allow AT

Then I listed the nft tables and the newly added AT-filter table.

root@apu:/usr/local/bin/nft-geo-filter# nft list tables
table ip filter
table ip6 filter
table ip nat
table netdev AT-filter
root@apu:/usr/local/bin/nft-geo-filter# nft list table netdev AT-filter
table netdev AT-filter {
        set filter-v4 {
                type ipv4_addr
                flags interval
                auto-merge
                elements = { 2.56.160.0/22, 2.56.208.0/22,
                            ... all the other ipv4 subnets....
                             217.196.144.0/20, 217.199.80.0/20 }
        }

        set filter-v6 {
                type ipv6_addr
                flags interval
                auto-merge
                elements = { 2001:628::/29,
                             2001:678:d::/48,
                            ... all the other ipv6 subnets....
                             2a0f:f080::/29 }
        }

        chain filter-chain {
                type filter hook ingress device enp1s0 priority -200; policy drop;
                ip6 saddr fe80::/10 accept
                ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept
                meta protocol != { ip, ip6 } accept
                ip saddr @filter-v4 accept
                ip6 saddr @filter-v6 accept
        }
}

Afterwards I wanted to allow another country: /usr/local/bin/nft-geo-filter/nft-geo-filter --table-family netdev --table-name SK-filter --interface enp1s0 --allow SK and then I was cut out of the server and can't connect via ssh from private IP subnet from range 192.168.0.0/16. Any idea what could go wrong here? I'm also using docker on this server.

frankofno commented 4 years ago

if you didn't save the ruleset to the conf, you can just reboot your server via the hosting panel. the rules from nft-geo should be gone then and you should be able to login via ssh again.

You set the policy to drop. So everything will be dropped, before it get's to the allow line. change it to accept and put a drop with a counter to the end.

chain filter-chain { type filter hook ingress device enp1s0 priority -200; policy drop; (=CHANGE TO ACCEPT) . . . nft add rule inet filter INPUT counter drop (LAST LINE IN RULESET)

peter-sc commented 4 years ago

Thanks for quick reply. Is there a way how to achieve my aim directly with some options passed to nft-geo-filter, without the need to edit the chain manually? I'd like to run the script in cron as suggested.

My understanding of the paragraph https://github.com/rpthms/nft-geo-filter#allow-mode-exceptions was that I can allow only some countries, and block all the other. But now it seems that manual editing is needed (as you suggested).

frankofno commented 4 years ago

haven't tried to allow only one country. But i guess you can define your personal allowed IP's in a chain with the drop at the end and save that rule to the conf. nft list ruleset > /etc/sysconfig/nftables.conf

than you do the nft-geo stuff with cron. I think the --exceptions are not yet included in the script, so make sure you connect from AT :)

rpthms commented 4 years ago

Hi @peter-sc

If you want to allow multiple countries in your filter set, you will also need to specify the country that was allowed before, in the arguments of nft-geo-filter. So, in your case you'd need to specify both AT and SK in the arguments.

/usr/local/bin/nft-geo-filter/nft-geo-filter --table-family netdev --table-name AT-SK-filter --interface enp1s0 --allow SK AT

You can't use 2 separate tables (AT-filter and SK-filter) in the allow mode, because the first table (let's assume the first table is AT-filter) will drop all the traffic that doesn't match its filter sets (i.e not from an Austrian IP), so the traffic would never even reach the second table (SK-filter).

rpthms commented 4 years ago

As for why you're not able to SSH from the private IP range, I'm not really sure. The rules to allow private IPs should have been in the chain when you used the --allow option. If you can post your ruleset over here somehow, I can help you debug the issue.

peter-sc commented 4 years ago

After deleting the newly created nft table and putting both allowed countries into one rule

/usr/local/bin/nft-geo-filter/nft-geo-filter --table-family netdev --table-name GEO-filter --interface enp1s0 --allow SK AT

the table was created:

    chain filter-chain {
                type filter hook ingress device enp1s0 priority -200; policy drop;
                ip6 saddr fe80::/10 accept
                ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept
                meta protocol != { ip, ip6 } accept
                ip saddr @filter-v4 accept
                ip6 saddr @filter-v6 accept
        }

and local ssh works correctly... strange, but it's working, thank you 👍