Convert ipset script to use nft

I run out of knowledge to be able to convert the following script to use nft instead of the now unavailable (on 1.4) ipset

I would use the set to filter source IPs on my wan-xxx fw zones.

Any help would be greatly appreciated.

#!/bin/bash
countryList="ch de gb nz"
firewallGroupName=countries-allowed
zonefiles="/config/zonefiles"
logLocation="/var/log/countries-allowed.log"

function loadcountry () {
     firewallGroupName=$1
     country=$2

     echo "Downloading country definition for $country..." >> $logLocation
     curl -o $zonefiles/${country}.zone http://www.ipdeny.com/ipblocks/data/countries/${country}.zone -q
     echo "Adding proper formating to $country zone file" >> $logLocation
     sed -i -e "s/^/add $firewallGroupName /" $zonefiles/${country}.zone
     echo "Creating/Modifing Temp file to load into $firewallGroupName" >> $logLocation
     cat $zonefiles/${country}.zone >> $zonefiles/country-load.tmp
}

echo "Flushing existing IPSET entries for $firewallGroupName" >> $logLocation
/sbin/ipset flush $firewallGroupName

for country in $countryList; do
     loadcountry $firewallGroupName $country
done

echo "Restoring IPSET entries for $countryList into $firewallGroupName firewall group" >> $logLocation
/sbin/ipset restore < $zonefiles/country-load.tmp

echo "Cleaning up temporary files" >> $logLocation
rm $zonefiles/country-load.tmp

Try this

#!/bin/bash

countryList="ch de gb nz"
firewallSetName=countries-allowed
zonefiles="/config/zonefiles"
logLocation="/var/log/countries-allowed.log"

nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0\; }
nft add set inet filter $firewallSetName { type ipv4_addr\; }

function loadcountry () {
     firewallSetName=$1
     country=$2

     echo "Downloading country definition for $country..." >> $logLocation
     curl -o $zonefiles/${country}.zone http://www.ipdeny.com/ipblocks/data/countries/${country}.zone -q

     echo "Adding proper formating to $country zone file" >> $logLocation
     sed -i -e "s/^/add element inet filter $firewallSetName {/" -e "s/$/}/" $zonefiles/${country}.zone

     echo "Loading IPs from $country into $firewallSetName set" >> $logLocation
     nft -f $zonefiles/${country}.zone
}

nft flush set inet filter $firewallSetName

for country in $countryList; do
     loadcountry $firewallSetName $country
done

nft list set inet filter $firewallSetName

Also remember that nftables does not automatically create rules that use the sets, so you need to manually create rules that use your new set. For example, to drop all packets not coming from one of the countries in your list, you would add a rule like:

nft add rule inet filter input ip saddr @countries-allowed accept
nft add rule inet filter input drop

Edit: here old link

Thanks, will give this a try later this evening and let you know.

In terms of rule, with the ipset method of old I simply referenced the ipset group name that was created in my standard config file and use a negation rule to block access from all countries not in my allowed list via that group name - countries-allowed.

Can the same be done with the nft approach as other than the script to populate the nft set that would keep my config contained in my config.boot file?

For 1.4 we have geoip

But unfortunately, it cannot work with groups, and I would have to add a rule per country in multiple locations.

You can add all country in one rule:

        rule 4 {
            action drop
            description drop-by-country
            log enable
            source {
                geoip {
                    country-code br
                    country-code by
                    country-code cn
                    country-code in
                    country-code ru
                }
            }
        }

Works on 1.4-rolling-202306260317.

3 Likes

Cool! wasn’t aware of that.

I think this should work in that case.

        rule 10 {
            action drop
            description "white listed countries only"
            source {
                geoip {
                    country-code ch
                    country-code de
                    country-code gb
                    country-code nz
                    country-code sg
                    country-code us
                    inverse-match
                }
            }
        }
1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.