## this assumes eth0 is LAN and eth1 is WAN, modify as needed flush ruleset ## change these define wan = eth1 define lan = eth0 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 define cs5ports = {123,3478-3479,25565} # high priority ports udp + tcp define af41ports = {10000,8801-8810} # jitsi meet, and zoom table inet filter { # if you want to do flow offloading, uncomment this, fix the devices (should be lan and wan) ## and uncomment the lines in the forward path below. ## if you do offloading, then only the first packet from offloaded flows will go through the full path ## so if you want comprehensive dscp marking in the nftables, then you shouldn't do offloading. #flowtable fastpath { # hook ingress priority 0 devices = {eth1,eth0}; #} 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, # if you want to allow from wan or other networks, add them to the iifname check iifname $lan ct state new tcp dport ssh meter ssh-meter4 {ip saddr limit rate 10/minute burst 15 packets} accept iifname $lan 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; ## tcp MSS clamping, https://wiki.nftables.org/wiki-nftables/index.php/Mangling_packet_headers tcp flags syn tcp option maxseg size set 1450 # or "set rt mtu" according to reference # if you want to do flow offloading try this? #ip protocol {tcp,udp} flow offload @fastpath #ip6 nexthdr {tcp,udp} flow offload @fastpath ct state established,related accept iifname $wan ct status dnat accept # for port forwarding, apparently needed? 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 { map portmaps { type inet_service : ipv4_addr elements = {3074 : 10.13.17.33, 8888 : 10.13.17.91 } # set these up to map ports to specific internal IPs } 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; iifname $wan dnat to tcp dport map @portmaps iifname $wan dnat to udp dport map @portmaps #if you want to do a DMZ style "all ports sent to this address" do this: # iifname $wan ip protocol {tcp,udp} dnat to 10.38.99.107 # if you want to hijack all DNS to go to the router's port 53 (or substitute a different dest port) #iifname $lan udp dport 53 redirect to 53 } } # experimental ingress washing feature. This can avoid problems with for example Comcast sending cs1 tag # and slowing your ingress connection table netdev tagingress { set lowpriosrc4 { typeof ip saddr elements = {10.29.31.101} # add ip addresses you want to down-prioritize, like for example if you want to punish YouTube. } set lowpriosrc6 { typeof ip6 saddr elements = {fe80::9091:1212} # add ip6 addresses you want to down-prioritize } ### EDIT BELOW: set device for wanin and for lanin chain dscpwanin { type filter hook ingress device eth0.2 priority 0; ## EDIT ME: set the device here ip dscp set cs0 ip6 dscp set cs0 jump porttags } chain dscplanin { type filter hook ingress device br-lan priority 0; ## EDIT ME: set the device here ip dscp set cs0 ip6 dscp set cs0 jump porttags } chain porttags { ## VOIP servers UDP traffic ip saddr $voipservers ip protocol udp ip dscp set cs6 ip daddr $voipservers ip protocol udp ip dscp set cs6 #ntp, playstation network ports and minecraft java edition udp dport $cs5ports ip dscp set cs5 udp dport $cs5ports ip6 dscp set cs5 udp sport $cs5ports ip dscp set cs5 udp sport $cs5ports ip6 dscp set cs5 # jitsi meet and zoom udp sport $af41ports ip dscp set af41 udp dport $af41ports ip dscp set af41 #down prioritize certain source/dest ip saddr @lowpriosrc4 ip dscp set cs1 ip6 saddr @lowpriosrc6 ip6 dscp set cs1 ip daddr @lowpriosrc4 ip dscp set cs1 ip6 daddr @lowpriosrc6 ip6 dscp set cs1 } } ## lets create a tagger table for more sophisticated tagging that ## can't happen at ingress since that's too early in the packet ## processing chain table inet cttags { # map dscpct { # typeof ip dscp : ct mark # elements = { # cs1 : 1, ... # } # } # map ctdscp{ # typeof ct mark : ip dscp # elements = { # 1 : cs1,... # } # } chain cttags { type filter hook postrouting priority 0; policy accept; ## if you want to trust the DSCP tags set on stuff coming ## from your LAN and restore those same tags for inbound ## from the same connection. This will interfere with the ## other use of connmark below unless we check for it # iifname $lan ct mark != 0x55 ct mark set ip dscp map @dscpct # iifname $wan ct mark != 0x55 ip dscp set ct mark map @ctdscp ## 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 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 < 50 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 } }