nftables running in OpenWrt (Perfectly)

Hi everyone, I have been able to run nftables on my WRT3200ACM after several attempts and I want to share it with anyone who is interested.
Download its version in my case:
https://downloads.openwrt.org/releases/19.07.5/targets/mvebu/cortexa9/openwrt-imagebuilder-19.07.5-mvebu-cortexa9.Linux-x86_64.tar.xz
Unzip.
vim /include/target.mk
and add:
DEFAULT_PACKAGES: = uhttpd luci-mod-admin-full luci-theme-bootstrap luci-app-opkg luci-proto-ppp libiwinfo-lua luci-proto-ipv6 rpcd-mod-rrdns base-files libc libgcc busybox dropbear mtd opkg netifd fstools uclient-fetch logd urandom-seed urngd uci
DEFAULT_PACKAGES.router: = dnsmasq ppp ppp-mod-pppoe odhcpd-ipv6only odhcp6c nftables kmod-nft-core kmod-nft-nat kmod-nfnetlink kmod-nft-nat6 kmod-nft-netdev kmod-nft-offload kmod-nft-bridge kmod-bridge kmod-nft-arp kmod-nft-fib
Compile.
And voila, don't install luci-ssl this will add the iptables firewall.
When you install and configure ssh, upload an nftables.conf to / etc
My nftables.conf
#!/usr/sbin/nft -f

table inet raw {

    chain PREROUTING {
            type filter hook prerouting priority -300; policy accept;
    }

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

table inet mangle {

    chain PREROUTING {
            type filter hook prerouting priority -150; policy accept;
    }

    chain INPUT {
            type filter hook input priority -150; policy accept;
    }

    chain FORWARD {
            type filter hook forward priority -150; policy accept;
                #tcp flags & (syn|rst) == syn counter tcp option maxseg size set rt mtu
    }

    chain POSTROUTING {
            type filter hook postrouting priority -150; policy accept;
                #counter meta mark set 0x100000
                #mark 0x100000 counter ip dscp set 0x00
                #counter meta mark set 1
    }

table ip nat {

    chain PREROUTING {
            type nat hook prerouting priority -100; policy accept;
    }

    chain INPUT {
            type nat hook input priority -100; policy accept;
    }

    chain POSTROUTING {
            type nat hook postrouting priority -100; policy accept;
                oifname "eth1.2" masquerade fully-random
    }

table inet filter {

    chain INPUT {
            type filter hook input priority 0; policy drop;
                ct state related,established counter accept
                udp sport bootpc udp dport bootps counter accept
                udp sport bootps udp dport bootpc counter accept
                udp sport dhcpv6-server udp dport dhcpv6-client counter accept
                udp sport dhcpv6-client udp dport dhcpv6-server counter accept                     
                ip protocol igmp counter accept
                meta iifname != "eth1.2" counter accept
                #ct state untracked counter goto NOTRACK
                counter drop
    }

    chain FORWARD {
            type filter hook forward priority 0; policy drop;
                ct state related,established counter accept
                meta iifname != "eth1.2" counter accept
                counter drop
    }

    chain OUTPUT {
            type filter hook output priority 0; policy accept;
                #ip daddr 239.255.255.250 counter drop
    }                                                       

add in rc.local
/usr/sbin/nft -f /etc/nftables.conf

4 Likes

hello i'm interested for mikrotik hap ac2 :slight_smile:

thanks for you work !

Hello, I am happy to help you. Thanks
For Luci with ssl, install libustream-mbedtls20150806, px5g

Here I leave my current nftables.conf with dscp per flow and more, it can serve as a reference

#!/sbin/nft -f
# ipv4/ipv6 Simple & Safe Firewall

flush ruleset

table netdev filter {
	
	chain wanin {
		type filter hook ingress device eth1.2 priority -500;
		    ip saddr 8.8.8.8 udp sport 53 counter drop
	}
        
	chain lanin {
	        type filter hook ingress device br-lan priority -500;
        }	
}	

table inet raw {
	
        chain PREROUTING {
		type filter hook prerouting priority -300; policy accept;
	}

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



table inet mangle {
	
        chain PREROUTING {
		type filter hook prerouting priority -150; policy accept;
	}

	chain INPUT {
		type filter hook input priority -150; policy accept;
		    #ct state invalid counter reject 
		    ip frag-off & 0x1fff != 0 counter reject
		    tcp flags & (fin | syn | rst | psh | ack | urg) == fin | syn | rst | psh | ack | urg counter reject
		    tcp flags & (fin | syn | rst | psh | ack | urg) == 0x0 counter reject
		    tcp flags syn tcp option maxseg size 1-536 counter reject
                    tcp flags & (fin|syn|rst|ack) != syn ct state new counter reject
		    mark & 0xff0 == 0x130 counter ip dscp set af22 return

	# real-time application
	## Rocket league
	udp dport 7000-9000 \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af41 return

	## ICMP
	ip protocol icmp \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af41 return

	## TCP low-flow
	meter wan-11-tcp { tcp sport . ip saddr timeout 10s limit rate 8 kbytes/second burst 16 kbytes } \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af42 return

	## UDP low-flow
	meter wan-11-udp { udp sport . ip saddr timeout 10s limit rate 8 kbytes/second burst 16 kbytes } \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af42 return

	# TCP midium-flow
	meter wan-12 { tcp sport . ip saddr timeout 3s limit rate 64 kbytes/second burst 512 kbytes } \
	meta mark set mark & 0xfffff00f ^ 0x120 counter ip dscp set af31 return

	# TCP high-flow & UDP {midium,high}-flow (default)
	meta mark set mark & 0xfffff00f ^ 0x130 counter ip dscp set af22
	}

	chain FORWARD {
		type filter hook forward priority -150; policy accept;
                    #tcp flags & (syn|rst) == syn counter tcp option maxseg size set rt mtu
	}

#	chain OUTPUT {
#		type route hook output priority -150; policy accept;
#	}

	chain POSTROUTING {
		type filter hook postrouting priority -150; policy accept;
		    mark & 0xff0 == 0x130 counter ip dscp set af23 return

	# internal traffic
	ip saddr 10.210.120.32/27 \
	meta mark set mark & 0xfffff00f ^ 0x200 counter ip dscp set af21 return

	# real-time application
	## Rocket league
	udp sport 7000-9000 \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af41 return

	## ICMP
	ip protocol icmp \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af41 return

	## TCP low-flow
	mark & 0xff0 != 0x120 \
	meter lan-11-tcp { tcp dport . ip daddr timeout 10s limit rate 16 kbytes/second burst 32 kbytes } \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af42 return

	## UDP low-flow
	mark & 0xff0 != 0x120 \
	meter lan-11-udp { udp dport . ip daddr timeout 10s limit rate 16 kbytes/second burst 32 kbytes } \
	meta mark set mark & 0xfffff00f ^ 0x110 counter ip dscp set af42 return

	# TCP midium-flow
	meter lan-12 { tcp dport . ip daddr timeout 3s limit rate 512 kbytes/second burst 2 mbytes } \
	meta mark set mark & 0xfffff00f ^ 0x120 counter ip dscp set af31 return

	# TCP high-flow & UDP {midium,high}-flow (default)
	meta mark set mark & 0xfffff00f ^ 0x130 counter ip dscp set af23
	}
}



table ip nat {
	
        chain PREROUTING {
		type nat hook prerouting priority -100; policy accept;
		    #iif br-lan ether saddr 60:36:DD:7F:9E:32 udp dport 53 counter dnat 1.1.1.1:53
		    iif br-lan ip daddr { 8.8.8.8, 8.8.4.4 } udp dport 53 counter dnat 10.210.120.33:53
		    iif br-lan udp dport 53 counter dnat 10.210.120.33:53
		    iif br-lan tcp dport 53 counter dnat 10.210.120.33:53
		    #iif eth1.2 tcp dport 4321 counter dnat 10.210.120.47:80
		    #iif eth1.2 ip protocol icmp counter dnat 10.210.120.32/27
	}

	chain INPUT {
		type nat hook input priority -100; policy accept;
	}

	chain POSTROUTING {
		type nat hook postrouting priority -100; policy accept;
		    oif "eth1.2" counter masquerade 
		    #persistent
	}
}



table inet filter {
	
        chain INPUT {
		type filter hook input priority 0; policy accept;
                    ct state established,related counter accept
		    ct state invalid counter reject
		    #ip protocol icmp counter accept
		    meta iif br-lan counter accept
		    iif lo counter accept
                    #udp sport bootpc udp dport bootps counter accept
                    ip saddr 10.0.0.0/8 udp sport bootps udp dport bootpc counter accept
		    meta l4proto icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } counter accept
                    #udp sport dhcpv6-server udp dport dhcpv6-client counter accept
                    #udp sport dhcpv6-client udp dport dhcpv6-server counter accept                     
                    #ip protocol igmp counter accept
                    #ct state untracked counter goto NOTRACK
                    counter reject
	}

	chain FORWARD {
		type filter hook forward priority 0; policy drop;
                    ct state established,related counter accept
		    iif eth1.2 ct status dnat counter accept
		    ct state invalid counter reject
		    #meta iif br-lan ether saddr 84:38:38:F3:6E:F4 ip daddr youtube.com counter drop comment "Samu"
		    #meta iif br-lan ether saddr 16:A4:CE:11:02:F1 ip daddr youtube.com counter drop comment "Nata"
		    #meta iif br-lan ether saddr 18:CF:5E:43:35:8A ip daddr youtube.com counter drop comment "Portatil"
		    #iif br-lan ether saddr 60:36:DD:7F:9E:32 counter accept
		    iif br-lan udp dport { 443, 80, 5353 } counter reject
		    iif br-lan tcp dport { 5228, 5222, 5229 } counter reject
		    oif eth1.2 counter accept
		    #meta iif br-lan oif eth1.2 counter accept
                    counter reject
	}

	chain OUTPUT {
		type filter hook output priority 0; policy accept;
		    oif lo counter accept
		    ct state established,related counter accept
		    ct state invalid counter drop
		    oif br-lan counter accept
		    oif eth1.2 ct state invalid counter drop
		    oif eth1.2 counter accept
                    ip daddr 239.255.255.250 counter drop
	}                                                       

}	


Something else, if you want to log the connections you choose, install libnetfilter-log1, ulogd, ulogd-mod-nflog, ulogd-mod-extra.
Configure ulogd.conf
plugin = "/ usr / lib / ulogd / ulogd_inppkt_NFLOG.so"
plugin = "/ usr / lib / ulogd / ulogd_filter_IFINDEX.so"
plugin = "/ usr / lib / ulogd / ulogd_filter_IP2STR.so"
plugin = "/ usr / lib / ulogd / ulogd_filter_PRINTPKT.so"
plugin = "/ usr / lib / ulogd / ulogd_output_LOGEMU.so"
plugin = "/ usr / lib / ulogd / ulogd_raw2packet_BASE.so"

stack = log1: NFLOG, base1: BASE, ifi1: IFINDEX, ip2str1: IP2STR, print1: PRINTPKT, emu1: LOGEMU

[emu1]
file = "/ tmp / log / nftables.log"
sync = 1

Insert the rules where you want the log, example;
counter log prefix "REJECT" group 0 reject
To see;
tail -f /tmp/log/nftables.log

And you can use cron to clear the log or put it on a USB.
0 11,23 * * * /etc/init.d/ulogd stop && rm /tmp/log/nftables.log && /etc/init.d/ulogd start
1 Like

Hi, if I want to just add some tproxy rules with nftables without migrating the firewall, which modules are needed?
I installed nftables-json through LuCI, and tried the example on nftables manual. However:

/etc/nftables.conf:4:3-34: Error: Could not process rule: No such file or directory
tcp dport 60000 tproxy to :10000
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I guess it's missing modules. I installed kmod-ipt-tproxy and iptables-mod-tproxy but it's still the same.

I think it needs an nftables tproxy module, not ipt/iptables modules.

It's possible the tproxy stuff isn't yet available in nftables versions that OpenWrt is using?

1 Like

I have error..how to fix it?

* opkg_install_cmd: Cannot install package kmod-bridge.
make[2]: *** [Makefile:158: package_install] Error 255
make[1]: *** [Makefile:118: _call_image] Error 2
make: *** [Makefile:208: image] Error 2

Your script worked great for me on a dir-882, on rc1 it's the fastest version of openwrt i've seen yet. Thanks.