Netfilter new school with NFTABLES

Requirements

zcat /proc/config.gz | grep NF_TABLES

Ubuntu

apt install nftables
systemctl status nftables
mv -i /etc/nftables.conf /etc/nftables.conf.dist

Slackware

slackpkg install nftables iptables libnftnl libpcap libnl3 dbus-1
ls -lF /etc/nftables/

Make sure you have no interfering rules there (could be caused by Docker for example)

iptables -L -v -n
iptables -L -v -n -t nat
iptables -L -v -n -t mangle
nft list ruleset

Block-all policy setup

Default policy can only be accept or drop. But reject can still be defined as last and ipso-facto default rule nevertheless.

We’re going for a very specific setup – we want to REJECT, not just DROP

vi /etc/nftables.conf

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;

        iifname lo accept
        iifname != lo ip daddr 127.0.0.0/8 reject
        iifname != lo ip6 daddr ::1 reject

        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept

        #tcp dport 2222 accept

        ct state established,related accept
        reject
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
        reject
    }

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

        # established,related,invalid

Block front-facing NIC only

an alternative would be policy ACCEPT and REJECT only the front-facing interface (here xenbr0)

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy accept;

        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept

        #iifname xenbr0 tcp dport 2222 accept

        iifname xenbr0 ct state established,related accept
        iifname xenbr0 reject with tcp reset
        iifname xenbr0 reject with icmp type host-unreachable
        iifname xenbr0 reject
    }
}

and for a workstation e.g.

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy accept;

        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept

        iifname eth0 ct state established,related accept
        iifname eth0 reject with tcp reset
        iifname eth0 reject with icmp type host-unreachable
        iifname eth0 reject

        iifname wlan0 ct state established,related accept
        iifname wlan0 reject with tcp reset
        iifname wlan0 reject with icmp type host-unreachable
        iifname wlan0 reject
    }

    # NAT --> accept
    chain forward {
        type filter hook forward priority filter; policy accept;
    }

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

note the tcp vs. udp reject rules will be translated accordingly by the engine

        meta l4proto tcp iifname "xenbr0" reject with tcp reset
        meta nfproto ipv4 iifname "xenbr0" reject with icmp type host-unreachable

NAT

static front-facing address

flush ruleset

table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100;
        ip saddr INTERNAL-CIDR oif FACING-INTERFACE snat PUBLIC-IP;
    }
}

dynamic front-facing address

vi /etc/nftables.conf

    # NAT --> accept
    chain forward {
            type filter hook forward priority 0; policy accept;
    }

table ip nat {
        # DNAT
        chain prerouting {
                type nat hook prerouting priority -100;
                #iifname eth0 tcp dport 80 dnat x.x.x.x
        }

        # SNAT
        chain postrouting {
                type nat hook postrouting priority 100;
                oifname eth0 masquerade
        }
}

another example

table inet my_nat {
        chain my_masquerade {
                type nat hook postrouting priority srcnat; policy accept;
                oifname "ppp0" masquerade
        }
}

Ready to go

apply on Ubuntu

    systemctl status nftables
    systemctl start nftables
    systemctl enable nftables
    systemctl reload nftables

or on Slackware at boot time

vi /etc/rc.d/rc.inet1

echo -n SNAT for 10.9.9.0/24...
echo 1 > /proc/sys/net/ipv4/ip_forward
/usr/sbin/nft -f /etc/nftables.conf && echo done || echo FAIL

Acceptance

nft list ruleset

Additional notes

flush a single table

nft flush table inet filter

If you want to be more precise on what kind of ICMP traffic you’re letting pass through, here are some hints

#icmp type echo-request accept
#icmpv6 type {echo-request,nd-neighbor-solicit} accept

also something for IPv6 here

# accept neighbour discovery otherwise connectivity breaks
ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept

Testing

during testing phases on a remote server, avoid shooting yourself in the pants

crontab -e

*/5 * * * * nft flush ruleset

proceed (and cross fingers)

nft -f /etc/nftables.conf
nft list ruleset

then DO NOT FORGET TO GET RID OF THAT CRON JOB

TODO

Let’s filter outbound traffic also, shall we?

Resources

https://wiki.nftables.org/wiki-nftables/index.php/Operations_at_ruleset_level

https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes

https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains

https://wiki.gentoo.org/wiki/Nftables

https://wiki.gentoo.org/wiki/Nftables/Examples

https://wiki.archlinux.org/index.php/nftables

https://linux-audit.com/nftables-beginners-guide-to-traffic-filtering/

https://unix.stackexchange.com/questions/419851/when-and-how-to-use-chain-priorities-in-nftables

icmp

http://shouldiblockicmp.com/

nat

https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)

https://superuser.com/questions/985800/complete-masquerading-nat-example-using-nftables-on-linux

https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)

https://www.it-connect.fr/chapitres/configurer-le-nat-sous-nftables/

return-rst

https://wiki.archlinux.org/title/nftables

https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes

https://serverfault.com/questions/157375/reject-vs-drop-when-using-iptables

Nftables opening gmabit https://discourse.pi-hole.net/t/nftables-opening-gmabit/28830

Rejecting traffic https://wiki.nftables.org/wiki-nftables/index.php/Rejecting_traffic

ops

https://wiki.archlinux.org/title/nftables#Flush_table

https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains


GUIDES | LECTURES | BENCHMARKS | SMTP HEALTH