NFtables and QoS in 2021

yes, we'll figure out how to get it auto-loaded later

modprobe nf_nat
modprobe nft_masq
modprobe nft_chain_nat

I'm just guessing here based on what's loaded on my desktop.

You can put those commands before the nft command in rc.local

Not sure because I don't have an openwrt device available right now, but it might be enough to list those modules in /etc/modules

1 Like

No Always not

My router renew each every 3 secondes the new dhcp at my pc

But i has access to putty and winscp

ok is good now :wink: i has changed my name of interface !

firewall is disabled i has access to internet

my firewall is empty

i has put the script like this


## this assumes eth0 is LAN and eth1 is WAN, modify as needed

flush ruleset

## change these

define wan = eth1
define lan = br-lan
define guest = eth0.10 # or remove these if you don't use guest or iot networks
define iot = eth0.5 ## but be sure to also remove the reference to them below

define bulksize = 35000000 ## total transfer before being sent to CS1
define voipservers = {10.0.98.113} ## add ipv4 addresses of fixed voip / telephone servers you use here

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

		# established/related connections
		ct state established,related accept

		# loopback interface
		iifname lo accept

		## icmpv6 is a critical part of the protocol, we just
		## accept everything, you can lookin to making this
		## more restrictive but be careful
		ip6 nexthdr icmpv6 accept

		# we are more restrictive for ipv4 icmp
		ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept

		ip protocol igmp accept

		ip protocol icmp meta iifname $lan accept

		## ntp protocol accept from LAN
		udp dport ntp iifname $lan accept

		## DHCP accept
		iifname $lan ip protocol udp udp sport bootpc udp dport bootps log prefix "FIREWALL ACCEPT DHCP: " accept

		## DHCPv6 accept from LAN
		iifname $lan udp sport dhcpv6-client udp dport dhcpv6-server accept

		## allow dhcpv6 from router to ISP
		iifname $wan udp sport dhcpv6-server udp dport dhcpv6-client accept

		# SSH (port 22), limited to 10 connections per minute per source host,
		# you might prefer to not allow this from WAN for
		# OpenWrt, in which case you should also add an
		# iifname $lan filter in the front so we're only
		# allowing from LAN
		
		ct state new tcp dport ssh meter ssh-meter4 {ip saddr limit rate 10/minute burst 15 packets} accept
		ct state new ip6 nexthdr tcp tcp dport ssh meter ssh-meter6 {ip6 saddr limit rate 10/minute burst 15 packets} accept 

		## allow access to LUCI from LAN
		iifname $lan tcp dport {http,https} accept

		## DNS for main LAN, we limit the rates allowed from each LAN host to reduce chance of denial of service
		iifname $lan udp dport domain meter dommeter4 { ip saddr limit rate 240/minute burst 240 packets} accept
		iifname $lan udp dport domain meter dommeter6 { ip6 saddr limit rate 240/minute burst 240 packets} accept

		iifname $lan tcp dport domain meter dommeter4tcp { ip saddr limit rate 240/minute burst 240 packets} accept
		iifname $lan tcp dport domain meter dommeter6tcp { ip6 saddr limit rate 240/minute burst 240 packets} accept

		## allow remote syslog input? you might want this, or remove this
		
		# iifname $lan udp dport 514 accept

		counter log prefix "FIREWALL INPUT DROP: " drop
	}

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

	    ct state established,related accept

	    iifname lo accept
	    iifname {$guest,$iot} oifname $lan drop ## guests can't connect to LAN
	    iifname {$lan,$guest,$iot} oifname $wan accept ## allow inside to forward to WAN

	    counter log prefix "FIREWALL FAIL FORWARDING: " drop
	}
}

## masquerading for ipv4 output on WAN
table ip masq {
	chain masqout {
	    type nat hook postrouting priority 0; policy accept;
	    oifname $wan masquerade

	}

	## this empty table is required to make the kernel do the unmasquerading
	chain masqin {
	    type nat hook prerouting priority 0; policy accept;

	}
	
}

## lets create a tagger table

table inet tags {
      #chain wanin {
      #	    type filter hook eth1 device eth1 priority 0; ## FIXME, this can't be a variable so put your WAN device here
		# jump tagchain
      #}

      chain tagrouted {
      	    type filter hook postrouting priority 0; policy accept;
	    jump cttags
      }


      chain cttags {
	    ip protocol tcp tcp sport != {2049} ip dscp < af41 ct bytes ge $bulksize ip dscp set cs1
            ip6 nexthdr tcp tcp sport != {2049} ip6 dscp < af41 ct bytes ge $bulksize ip6 dscp set cs1
  	    ip protocol udp ip dscp < cs5 udp dport != {http,https,domain} udp sport != {http,https,domain} meter udp4meter {ip saddr . ip daddr . udp sport . udp dport limit rate over 200/second burst 100 packets } counter ct mark set 0x55
            ip6 nexthdr udp ip6 dscp < cs5 udp dport != {http,https,domain} udp sport != {http,https,domain} meter udp6meter {ip6 saddr . ip6 daddr . udp sport . udp dport limit rate over 200/second burst 100 packets } counter ct mark set 0x55

            ct mark 0x55 numgen random mod 10000 < 5 ct mark set 0x00 comment "small probability to unmark over-threshold connections"

## prioritize small packet udp flows on any ports:
            ct mark != 0x55 ip protocol udp ip dscp < cs5 udp dport != {http,https,domain} udp sport != {http,https, domain} ct avgpkt 0-450 counter ip dscp set cs5
            ct mark != 0x55 ip6 nexthdr udp ip6 dscp < cs5 udp dport != {http,https,domain} udp sport != {http,https,domain} ct avgpkt 0-450 counter ip6 dscp set cs5
	    jump tagchain
      }

      chain tagchain {


	    ## VOIP servers UDP traffic
            ip saddr $voipservers ip protocol udp ip dscp set cs6
            ip daddr $voipservers ip protocol udp ip dscp set cs6

	    ## tag UDP that stays below 200pps and 450 bytes per packet to CS5 priority

            ## udp flows that have more than 200 packets per second get marked 0x55, then non 0x55 flows
            ## with avg packetsize less than 450 bytes get marked cs5
          
	  #playstation network port
	  udp dport 3478-3479 ip dscp set cs5
	  udp dport 3478-3479 ip6 dscp set cs5
	  udp sport 3478-3479 ip dscp set cs5
	  udp sport 3478-3479 ip6 dscp set cs5

          # minecraft java edition source
          tcp sport 25565 ip dscp set cs5
          tcp sport 25565 ip6 dscp set cs5

          # minecraft java edition dest
          tcp dport 25565 ip dscp set cs5
          tcp dport 25565 ip6 dscp set cs5

          # jitsi meet:
          udp sport 10000 ip dscp set af41
          udp dport 10000 ip dscp set af41
          # zoom udp
          udp sport {3478,3479,8801-8810} ip dscp set af41
          udp dport {3478,3479,8801-8810} ip dscp set af41


      }
      
}

Good it sounds like you got it working at the basic level. Try playing a game and do a packet capture on br-lan and see if the game packets from the internet get tagged because they are UDP that doesn't send too fast. (the ones from your game machine won't appear tagged because you capture them before the tagging happens)

1 Like

ok with wireshark then?

I have the mirroring port on hap ac2 I will configure it

mirrot source port lan2 my pc

mirror monitor port lan 4 my console game ?

hmmm I think mirror source port your CPU, mirror monitor port your PC, that means everything your CPU sends to the switch will get mirrored to your PC so you can see what's going on from your PC.

Also it looks like inet ingress is in kernel 5.10 and later: https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains so we will need to do something else for ingress, but we don't need ingress if we use Cake on egress of WAN and egress of LAN and don't use IFB

1 Like

ok so do you want configure cake and i has an idea i will add port in script like this you think ?

#call of duty  port
	  udp dport 3074 ip dscp set cs5
	  udp dport 3074 ip6 dscp set cs5
	  udp sport 3074 ip dscp set cs5
	  udp sport 3074 ip6 dscp set cs5

just a suggestion

i cofnigure sqm just like that ?

config queue 'eth1'
	option interface 'eth1'
	option qdisc 'cake'
	option script 'piece_of_cake.qos'
	option enabled '1'
	option download '56000'
	option upload '3200'
	option debug_logging '0'
	option verbosity '5'
	option linklayer 'ethernet'
	option overhead '44'

or like this ?

config queue 'eth1'
	option interface 'eth1'
	option qdisc 'cake'
	option script 'piece_of_cake.qos'
	option enabled '1'
	option upload '3200'
	option debug_logging '0'
	option verbosity '5'
	option linklayer 'ethernet'
	option overhead '44'
	option download '0'

config queue
	option enabled '1'
	option interface 'br-lan'
	option download '0'
	option upload '56000'
	option debug_logging '0'
	option verbosity '5'
	option qdisc 'cake'
	option script 'piece_of_cake.qos'
	option linklayer 'ethernet'
	option overhead '44'

So i'm modérate nat in my games is normal ?? @dlakelan

Maybe has a not firewall

I suggest to add all the game ports you think are relevant into a set and handle them all at once:

define gameports = {1234,3898,2924,15002} ## or whatever
....


	  udp dport $gameports ip dscp set cs5
	  udp dport $gameports ip6 dscp set cs5
	   udp sport $gameports ip dscp set cs5
	  udp sport $gameports ip6 dscp set cs5

In SQM config, I suggest to use layer_cake and diffserv4, and two queues, one on wan and one one br-lan

2 Likes

ok great just when I restart the router the firewall comes back

do I make the nftables.conf executables 0755?

No, but you must actually disable the regular firewall, and you need to start the nftables firewall somewhere, easiest is in rc.local but it could be good to start it earlier in the boot sequence. I'll defer to someone else to come up with a service script for that as I don't have any openwrt devices to test on.

In Luci to disable go to system > startup and find the firewall and click the button that says "enabled" to toggle it to "disabled"

1 Like

ok how can i see that i have the nftables firewall ??

from command line you can do:

nft list ruleset
1 Like

possibly the nftables package already has a service file and you can check in Luci to see if it's listed in startup.

1 Like

no it does not have service packages for the moment

GREAT JOB !! :wink:

root@OpenWrt:~# nft list ruleset
table inet filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                iifname "lo" accept
                ip6 nexthdr ipv6-icmp accept
                ip protocol icmp icmp type { destination-unreachable, router-adv                                                                                                                         ertisement, router-solicitation, time-exceeded, parameter-problem } accept
                ip protocol igmp accept
                ip protocol icmp iifname "br-lan" accept
                udp dport 123 iifname "br-lan" accept
                iifname "br-lan" ip protocol udp udp sport 68 udp dport 67 log p                                                                                                                         refix "FIREWALL ACCEPT DHCP: " accept
                iifname "br-lan" udp sport 546 udp dport 547 accept
                iifname "wan" udp sport 547 udp dport 546 accept
                ct state new tcp dport 22 meter ssh-meter4 size 65535 { ip saddr                                                                                                                          limit rate 10/minute burst 15 packets } accept
                ct state new ip6 nexthdr tcp tcp dport 22 meter ssh-meter6 size                                                                                                                          65535 { ip6 saddr limit rate 10/minute burst 15 packets } accept
                iifname "br-lan" tcp dport { 80, 443 } accept
                iifname "br-lan" udp dport 53 meter dommeter4 size 65535 { ip sa                                                                                                                         ddr limit rate 240/minute burst 240 packets } accept
                iifname "br-lan" udp dport 53 meter dommeter6 size 65535 { ip6 s                                                                                                                         addr limit rate 240/minute burst 240 packets } accept
                iifname "br-lan" tcp dport 53 meter dommeter4tcp size 65535 { ip                                                                                                                          saddr limit rate 240/minute burst 240 packets } accept
                iifname "br-lan" tcp dport 53 meter dommeter6tcp size 65535 { ip                                                                                                                         6 saddr limit rate 240/minute burst 240 packets } accept
                counter packets 69 bytes 5819 log prefix "FIREWALL INPUT DROP: "                                                                                                                          drop
        }

        chain forward {
                type filter hook forward priority filter; policy drop;
                ct state established,related accept
                iifname "lo" accept
                iifname { "eth0.5", "eth0.10" } oifname "br-lan" drop
                iifname { "eth0.5", "br-lan", "eth0.10" } oifname "wan" accept
                counter packets 0 bytes 0 log prefix "FIREWALL FAIL FORWARDING:                                                                                                                          " drop
        }
}
table ip masq {
        chain masqout {
                type nat hook postrouting priority filter; policy accept;
                oifname "wan" masquerade
        }

        chain masqin {
                type nat hook prerouting priority filter; policy accept;
        }
}
table inet tags {
        chain tagrouted {
                type filter hook postrouting priority filter; policy accept;
                jump cttags
        }

        chain cttags {
                ip protocol tcp tcp sport != 2049 ip dscp < af41 ct bytes >= 350                                                                                                                         00000 ip dscp set cs1
                ip6 nexthdr tcp tcp sport != 2049 ip6 dscp < af41 ct bytes >= 35                                                                                                                         000000 ip6 dscp set cs1
                ip protocol udp ip dscp < cs5 udp dport != { 53, 80, 443 } udp s                                                                                                                         port != { 53, 80, 443 } meter udp4meter size 65535 { ip saddr . ip daddr . udp s                                                                                                                         port . udp dport limit rate over 200/second burst 100 packets } counter packets                                                                                                                          0 bytes 0 ct mark set 0x00000055
                ip6 nexthdr udp ip6 dscp < cs5 udp dport != { 53, 80, 443 } udp                                                                                                                          sport != { 53, 80, 443 } meter udp6meter size 65535 { ip6 saddr . ip6 daddr . ud                                                                                                                         p sport . udp dport limit rate over 200/second burst 100 packets } counter packe                                                                                                                         ts 0 bytes 0 ct mark set 0x00000055
                ct mark 0x00000055 numgen random mod 10000 < 5 ct mark set 0x000                                                                                                                         00000 comment "small probability to unmark over-threshold connections"
                ct mark != 0x00000055 ip protocol udp ip dscp < cs5 udp dport !=                                                                                                                          { 53, 80, 443 } udp sport != { 53, 80, 443 } ct avgpkt 0-450 counter packets 49                                                                                                                          bytes 7306 ip dscp set cs5
                ct mark != 0x00000055 ip6 nexthdr udp ip6 dscp < cs5 udp dport !                                                                                                                         = { 53, 80, 443 } udp sport != { 53, 80, 443 } ct avgpkt 0-450 counter packets 1                                                                                                                         0 bytes 1402 ip6 dscp set cs5
                jump tagchain
        }

        chain tagchain {
                ip saddr 10.0.98.113 ip protocol udp ip dscp set cs6
                ip daddr 10.0.98.113 ip protocol udp ip dscp set cs6
                udp dport 3478-3479 ip dscp set cs5
                udp dport 3478-3479 ip6 dscp set cs5
                udp sport 3478-3479 ip dscp set cs5
                udp sport 3478-3479 ip6 dscp set cs5
                tcp sport 25565 ip dscp set cs5
                tcp sport 25565 ip6 dscp set cs5
                tcp dport 25565 ip dscp set cs5
                tcp dport 25565 ip6 dscp set cs5
                udp sport 10000 ip dscp set af41
                udp dport 10000 ip dscp set af41
                udp sport { 3478-3479, 8801-8810 } ip dscp set af41
                udp dport { 3478-3479, 8801-8810 } ip dscp set af41
                udp dport { 3074, 3659, 9308 } ip dscp set cs5
                udp dport { 3074, 3659, 9308 } ip6 dscp set cs5
                udp sport { 3074, 3659, 9308 } ip dscp set cs5
                udp sport { 3074, 3659, 9308 } ip6 dscp set cs5
        }
}
root@OpenWrt:~#

Perfect. I created a service file based on the super simple example in the wiki. It's now pushed to the repo. Might want to change its priority... not sure.

for info how to install the initscript.

1 Like

change its priority how?
ah yes

I add this file in etc.init.d

I name it nftables and put the script in it?

ok will reboot and i keep inform :wink:

Capture d’écran 2021-11-16 à 01.37.18
all the files are in 0755 on the other hand

yes, place script as /etc/init.d/nftables then make it executable... then

/etc/init.d/nftables enable
1 Like

you got ahead of me haha

ok the firewall is deactivated but when I restart it comes back I mean by it that it is not empty like when I put stop on firewall

/etc/init.d/firewall disable

to permanently disable the firewall, will survive a reboot.

1 Like