Skip to main content

nftables - Firewall

Basics

Using nftables as the successor to iptables makes life much more convenient. So I switched to nftables at my projects.

For debian (bookworm) it's necessary to enable the nftables service:

systemctl enable nftables.service

Default configuration file for nftables is located at: /etc/nftables.conf. I don't want to make big modifications at preinstalled files, so I just add an include statement for customized rules:

include "/etc/custom/nftables.rules" 

Here are some basic commands for nftables

List loaded ruleset

nft list ruleset

List sets 
The following command lists the set WHITELIST of table CUSTOM

nft list set inet CUSTOM WHITELIST
Basic ruleset for a server providing http/https services
#!/usr/sbin/nft -f

table inet CUSTOM {
    # empty set WHITELIST - will be filled dynamically by scripts
	set WHITELIST {
		type ipv4_addr
	}
	chain INPUT {
		type filter hook input priority 0; policy drop;

		# allow established/related connections
		ct state {established, related} accept

		# early drop of invalid connections
		ct state invalid drop

		# allow from loopback
		iifname lo accept

		# allow icmp (ipv4) - only from IP set WHITELIST
		ip protocol icmp ip saddr @WHITELIST accept

        # allow only ssh connections from IP set WHITELIST
		tcp dport {22} ip saddr @WHITELIST accept

		# allow web services
		tcp dport {80, 443} accept

		# allow internal container interface
		iifname "lxcbr0" ip daddr 10.0.3.1 accept

		# everything else drop
		drop
	}

	chain OUTPUT {
		type filter hook output priority 0; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority 0; policy drop;
		oifname "lxcbr0" accept
        iifname "lxcbr0" accept
	}
}

Updating nftables set

The following bash script updates the set WHITELIST with a dynamic IP address. The script should be executed periodically by a cron  job.

The variables 

  • ips
  • host

have to be modified.

#!/bin/bash
# Update ipset to let my dynamic IP in
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# nftables table and set
ipset=WHITELIST
table=CUSTOM

# dynamical IP for resolving via DNS
host=myurl.example.com

#IP for whitelisting
ips="127.0.0.1 127.0.0.2"

# hostname for logging
me=$(basename "$0")

ip=$(dig +short $host | tail -1)
if [ -z "${ip}" ]; then
    logger -t "${me}" "IP for ${host} not found"
    exit 1
fi

ips="${ips} ${ip}"

ret=`nft get element inet ${table} ${ipset} { ${ip} } > /dev/null 2>&1; echo $?`

if [[ ${ret} == "1" ]] then 
	nft flush set inet ${table} ${ipset}
	logger -t "${me}"  "Adding IP ${ip} to set ${ipset}."
	for i in ${ips}
	do
		logger -t "${me}"  "Adding IP ${i} to set ${ipset}."
		nft add element inet ${table} ${ipset} { ${i} }
	done
fi

exit 0