Nftables/iptables firewall paranoid setup ipv4 and ipv6

Dear openwrt users,

mayby im a little bit paranoid but im scared of mine home firewall setup that its secure enough. and everything im scared of is that i dont understand so the last week or so im reading and try to build my own firewall for nftables, to learn more about the firewall to be more secure.

how i read it the nftables are amazing because if for some examples a connection is made from the lan network to the internet, the connecting keeps excisting and is accepted. but if the same connection is made from the internet trough the lan it will be blocked because noone asked for it, no matter what port. (dont know if thats possible in ip tables but i like this a lot feels secure).

ct state vmap { established : accept, related : accept, invalid : drop }

now see the picture for the home network setup (sorry for the bad drawing if been using paint for years and trying out linux for the last month or so):

The router has three lan ports (eth0 for wan eth1 lan and eth2 lan), eth1 is connected to server running proxmox that runs:

  • minecraft server
  • logging server
  • website
  • mailing
  • rstp and ftp for iot camera's (hacked china stuff so that is really untrustworthy)

and eth2 is connected to a switch that is connected to:

  • iptv
  • IOT(light control device)
  • second router as AP

i can create inside the switch different vlans for each device, but now the problem the wifi.
Some wifi devices are untrusted and only can use the rstp and ftp server to control them like:

  • the china ip cameras

but some devices i trust like:

  • mine laptop after some port knocking.

some IOT devices i trust more than the china ip camera's and need to get connected to the internet but nothing else like:

  • printers (ntp)
  • nest thermostat
  • smart tv's
  • mobile phones
  • switch
  • etc.

so the i tought of a setup for vlans or ipaddress ranges that get ranked and only can connect lower ranks, The problems:

  1. If the ip address range is being used than no vlan is made only a lot of interfaces are made with diff ranges, the devices are setup by ranked, so they cant find each other. but if someone hacks a device change the ip adress of the device to the highest rank. they have fully control of the system.

  2. if the vlan setup is being used i cant catogirize the wifi because it hasnt vlans (only the second router can have a vlan and the same interface) but for example a rough iot wifi device could listen on the network.

The next two pieces of code would be the nfttables.conf the ip isnt quite ready yet beacse the input and forward iifnames and oifnames arnt connected to the defines. i did my best but im not even a novel just a noob trying to understand so big disclamer copy stuff from it on your own risk:

IP:

flush ruleset

#Defines
##interfaces
define wan = eth0.300
define wan6 = eth0.300

##Subnets ipv4 and ipv6
###local servers that don't need internet access like ftp, rstp, logging servers etc.
define net_ipv4_servers_local = 10.0.0.0/24
define net_ipv6_servers_local = fe00:0::/64
###online servers that need internet access like minecraft, websites, mailing server etc.
define net_ipv4_servers_online = 10.0.1.0/24
define net_ipv6_servers_online = fe00:1::/64
###The untrusted wifi and lan network where guests just can login
define net_ipv4_guests = 10.0.2.0/24
define net_ipv6_guests = fe00:2::/64
###The untrusted but fine serivices like chromecast printers nests thermostat that need acces the internet.
define net_ipv4_iot_online = 10.0.3.0/24
define net_ipv6_iot_online = fe00:3::/64
###The really untrusted services like ip camera's that only need a ntp and ftp server rstp server to send there data and control them.
define net_ipv4_iot_local = 10.0.4.0/24
define net_ipv6_iot_local = fe00:4::/64
###The hosts ip addresses like luci proxmox logging website (from the logging server).
define net_ipv4_local_hosts = 10.0.5.0/24
define net_ipv6_local_hosts = fe00:5::/64
###Trusted devices that can control everything like PC's/ mobile devices
define net_ipv4_home = 10.0.6.0/24
define net_ipv6_home = fe00:6::/64



#start ipv4/ipv6 filter
table inet filter{

	#prerouting for nat's
	chain prerouting {
		type nat hook prerouting priority 0; policy accept;
			#This is the rule, it says router when a packet arrives for tcp port 12345, that it is forward only the ssh port on a machine on the LAN. This is forwarded using #dnat - destination NAT, as its a ssh connection, and anything back from the machine on LAN is send back to machine sending the original packet. This is done in #prerouting it is done as soon as the packet enters the machine. A similar command would used if you wanted a WWW server on a local machine exported to the WAN so #people could connect over the internet. ipv6 needs brackeds for the ports like [ipv6]:port number
			#dnat to tcp dport map {12345 : 192.168.2.111}
	}

	#input every packet that received by the router drop the connection if there isnt a exeption
	chain input {
        type filter hook input priority 0; policy drop;
		#accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }

        #drop connections that arn't comming from the loopback
        iif != lo ip daddr 127.0.0.1/8 counter drop comment "drop connections to loopback not coming from loopback"
		iif != lo ip6 daddr ::1/128 counter drop comment "drop connections to loopback not coming from loopback"


        # allow loopback traffic, anything else jump to chain for further evaluation
        iifname vmap { lo : accept, $wan : jump inbound_wan, $home : jump inbound_home, $server_locale : jump inbound_server_locale , $server_online : jump inbound_server_online, $iot_locale : jump inbound_iot_locale , $iot_online : jump inbound_iot_online, $hosts : jump inbound_hosts , $gasten : jump inbound_gasten}
        }


	#Everything that being transmited trough the router to a differnt host. drop the connection if there isnt a exeption
	chain forward {
		type filter hook forward priority 0; policy drop;

		#accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }

        #Home is the highest rank so they can reach everything, but nothing can reach home
        iifname $home accept

        #Every interface that needs special rules before going to the internet
        oifname $wan iifname {$gasten : jump outbound_gasten, $iot_online : jump outbound_iot_online, $server_online : jump outbound_server_online}

        #Interfaces that can reach eachother only one way.
        meta iifname . meta oifname {$gasten . $server_online, $home . $hosts} accept

        }

	#the nat masquerade to hide every ip address ipv4 and ipv6
	chain postrouting {
	type nat hook postrouting priority 100; policy accept;

        #masquerade private IP addresses
        oifname "eth0" masquerade
    }

#chains from the input chain so packets received by the firewall itself
	##wan -> firewall
    chain inbound_wan {
    # The incomming packets from the wan port (nothing because if there is a connection from the home -> wan established thet connection will be accepted) only the server # ports that need to be accepted like 443 for a website and 25565 for minecraft
    }

	##home -> firewall
    chain inbound_home {

    }

	##server_locale -> firewall
    chain inbound_server_locale {
         #only the ntp
         udp dport {123} accept
    }

	##server_online -> firewall
    chain inbound_server_online {
         #only http https ntp dns and i think the minecraft server talks over the 25565 port accept
         tcp dport {53, 80, 123, 443 , 25565} accept
         udp dport {53, 123, 25565} accept
    }

	##IOT_locale -> firewall
    chain inbound_iot_locale {
         #only the ntp this is likeyly just the printers and two ip camera's
         udp dport {123} accept
    }

    ##IOT_online -> firewalll
    chain inbound_iot_online {
        #this is the scary one like nest thermostat chromecast smart tv's smart lights. they need a verarity of ports not knowing what they doing or talking to so TODO:more protection over here!

        accept
    }

    ##guests -> firewall
    chain inbound_gasten {
        #not knowing who is connected to your wifi dns http https ntp ports opened, TODO:check because gasten_inbound is more trustwothy than iot devices this is forwarded to the server online zone what everyone can reach else it is inpossible to reach minecraft etc. but mayby the ports of the servers need to be addet to reach or a dnat for the dns bc it isnt the same ip address to lookup the ddns to reach isnt going automatic to the right incomming port and forwarded ip addres. if the destination address matches the ddns ip then forward to the online server.
         tcp dport {53, 80, 123, 443} accept
         udp dport {53, 123} accept
    }

    ##hosts -> firewall
    chain inbound_hosts {
        #nothing needed like proxmox luci logging output running on this (logging output site is running on the local server line but forwarded to this subnet TODO:)
    }


#Chains from the forwarded chain so packets send from the firewall to a different host

    ##guest network untrusted cant reach Sh*t but safe modus so only dns http https ntp
    chain outbound_gasten {
        tcp dport {53, 80, 123, 443} accept
		udp dport {53, 123} accept
    }

	##IOT_online really dont know how to get this one safe
    chain outbound_iot_online {
        accept
   }

	##Server online all the neccasery ports that own online services use.
    chain outbound_server_online {
         #only http https ntp dns and i think the minecraft server talks over the 25565 port accept
         tcp dport {53, 80, 123, 443 , 25565} accept
         udp dport {53, 123, 25565} accept
    }

}




and the vlan one:

#remove every ruleset and build new ruleset
flush ruleset

#Defines
##nics with vlans there are 4096 vlan possabilities
## wan (eth0 with vlan 300 for internet acces) the vlans for ipv4 and ipv6 can be changed in the future, from isp.
define wan4 = eth0.300
define wan6 = eth0.300



##eth1 (lan port 1) and eth2 (lan port 2) for excample purpouse eth2 not connected
###local servers that don't need internet access like ftp, rstp, logging servers etc.
define server_locale = eth1.1
###online servers that need internet access like minecraft, websites, mailing server etc.
define server_online = eth1.50
###The untrusted wifi and lan network where guests just can login
define gasten = eth1.100
###The untrusted but fine serivices like chromecast printers nests thermostat that need acces the internet.
define iot_online = eth1.150
###The really untrusted services like ip camera's that only need a ntp and ftp server rstp server to send there data and control them.
define iot_locale = eth1.200
###The hosts ip addresses like luci proxmox logging website (from the logging server).
define hosts = eth1.250
###Trusted devices that can control everything like PC's/ mobile devices
define home = eth1.299



#start ipv4/ipv6 filter
table inet filter{

	#prerouting for nat's
	chain prerouting {
		type nat hook prerouting priority 0; policy accept;
			#This is the rule, it says router when a packet arrives for tcp port 12345, that it is forward only the ssh port on a machine on the LAN. This is forwarded using #dnat - destination NAT, as its a ssh connection, and anything back from the machine on LAN is send back to machine sending the original packet. This is done in #prerouting it is done as soon as the packet enters the machine. A similar command would used if you wanted a WWW server on a local machine exported to the WAN so #people could connect over the internet. ipv6 needs brackeds for the ports like [ipv6]:port number
			#dnat to tcp dport map {12345 : 192.168.2.111}
	}

	#input every packet that received by the router drop the connection if there isnt a exeption
	chain input {
        type filter hook input priority 0; policy drop;
		#accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }

        #drop connections that arn't comming from the loopback
        iif != lo ip daddr 127.0.0.1/8 counter drop comment "drop connections to loopback not coming from loopback"
		iif != lo ip6 daddr ::1/128 counter drop comment "drop connections to loopback not coming from loopback"


        # allow loopback traffic, anything else jump to chain for further evaluation
        iifname vmap { lo : accept, $wan4 : jump inbound_wan, $wan6 : jump inbound_wan, $home : jump inbound_home, $server_locale : jump inbound_server_locale , $server_online : jump inbound_server_online, $iot_locale : jump inbound_iot_locale , $iot_online : jump inbound_iot_online, $hosts : jump inbound_hosts , $gasten : jump inbound_gasten}
        }


	#Everything that being transmited trough the router to a differnt host. drop the connection if there isnt a exeption
	chain forward {
		type filter hook forward priority 0; policy drop;

		#accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }

        #Home is the highest rank so they can reach everything, but nothing can reach home
        iifname $home accept

        #Every interface that needs special rules before going to the internet
        oifname $wan4 iifname {$gasten : jump outbound_gasten, $iot_online : jump outbound_iot_online, $server_online : jump outbound_server_online}
		oifname $wan6 iifname {$gasten : jump outbound_gasten, $iot_online : jump outbound_iot_online, $server_online : jump outbound_server_online}

        #Interfaces that can reach eachother only one way.
        meta iifname . meta oifname {$gasten . $server_online, $home . $hosts} accept

        }

	#the nat masquerade to hide every ip address ipv4 and ipv6
	chain postrouting {
	type nat hook postrouting priority 100; policy accept;

        #masquerade private IP addresses ipv4
        oifname $wan4 masquerade
        #masquerade private IP addresses ipv6
        oifname $wan6 masquerade
    }

#chains from the input chain so packets received by the firewall itself
	##wan -> firewall
    chain inbound_wan {
    # The incomming packets from the wan port (nothing because if there is a connection from the home -> wan established thet connection will be accepted) only the server # ports that need to be accepted like 443 for a website and 25565 for minecraft
    }

	##home -> firewall
    chain inbound_home {

    }

	##server_locale -> firewall
    chain inbound_server_locale {
         #only the ntp
         udp dport {123} accept
    }

	##server_online -> firewall
    chain inbound_server_online {
         #only http https ntp dns and i think the minecraft server talks over the 25565 port accept
         tcp dport {53, 80, 123, 443 , 25565} accept
         udp dport {53, 123, 25565} accept
    }

	##IOT_locale -> firewall
    chain inbound_iot_locale {
         #only the ntp this is likeyly just the printers and two ip camera's
         udp dport {123} accept
    }

    ##IOT_online -> firewalll
    chain inbound_iot_online {
        #this is the scary one like nest thermostat chromecast smart tv's smart lights. they need a verarity of ports not knowing what they doing or talking to so TODO:more protection over here!

        accept
    }

    ##guests -> firewall
    chain inbound_gasten {
        #not knowing who is connected to your wifi dns http https ntp ports opened, TODO:check because gasten_inbound is more trustwothy than iot devices this is forwarded to the server online zone what everyone can reach else it is inpossible to reach minecraft etc. but mayby the ports of the servers need to be addet to reach or a dnat for the dns bc it isnt the same ip address to lookup the ddns to reach isnt going automatic to the right incomming port and forwarded ip addres. if the destination address matches the ddns ip then forward to the online server.
         tcp dport {53, 80, 123, 443} accept
         udp dport {53, 123} accept
    }

    ##hosts -> firewall
    chain inbound_hosts {
        #nothing needed like proxmox luci logging output running on this (logging output site is running on the local server line but forwarded to this subnet TODO:)
    }


#Chains from the forwarded chain so packets send from the firewall to a different host

    ##guest network untrusted cant reach Sh*t but safe modus so only dns http https ntp
    chain outbound_gasten {
        tcp dport {53, 80, 123, 443} accept
		udp dport {53, 123} accept
    }

	##IOT_online really dont know how to get this one safe
    chain outbound_iot_online {
        accept
   }

	##Server online all the neccasery ports that own online services use.
    chain outbound_server_online {
         #only http https ntp dns and i think the minecraft server talks over the 25565 port accept
         tcp dport {53, 80, 123, 443 , 25565} accept
         udp dport {53, 123, 25565} accept
    }

}



am i on the right track? of overthinking it? how would you keep everything save?

the idea is to make a lot of differnt DMZ to keep everything apart to keep things apart that need to be seperated so:

  1. servers that need to be online inside proxmox can be online
  2. servers that are local and have special cases:
  • ftp rstp only reached by the wifi camera's for the ftp and rstp
  • everything that logs like proxmox openwrt websites and minecraft can log inside the logging server for easy acces
  • The ftp rstp and logging server only can be reached trough hi ranked devices like a pc.
  1. the online servers that run services can be reached by the guest network (but by the ddns address and port number)
  2. everything untrusted blocked.

thanks for reading this, and trying to help me :slight_smile:
kind regards,
Elfje4life

For a start, why are you concerned that the default OpenWRT firewall and/or additional rules created through OpenWRT/luci are insufficient? Why do you think doing this manually will result in a better setup?

3 Likes

Dear krazeh,

Thank you for reading.
No that's not why Im doing this, I know for sure the openwrt default rules are enough. But that works on the iptables and I'm going to try to get my next openwrt buit to be using the nftables.

I really like the nftables rule that there is a one way setup also between interfaces where only connection are accepted where asked for. (I don't know if iptables can do the same)

But I think it's really easy to use because that will mean that a DMC or a IOT zone never can reach the lan/wlan zone but the lan/wlan can ask the DMZ and IOT zone for services that needed and setup a stable and safe connection.

Inside iptables trough luci you can do the same thing and opening the right ports for the services needed (lan wlan to service and back) but the connection stays open the IOT and DMZ will always have access to the lan wlan interface trough those ports.

This is what I understand of the difference between nftables and iptables, and a lot less rules to write.

Kind regards,
Elfje4life

Then OpenWRT will create appropriate nftable rules.

That's just standard connection tracking. IPtables does that (as does any other stateful firewall).

You will have to do exactly the same with nftables if you ever want anything in the IOT or DMZ zones to initiate the connection. If you don't then you wouldn't need port forwarding with iptables either.

1 Like

Dear krazeh,

Openwrt is opensource and its comunity driven, its really amazing to look at the source code for me its one big mystery how everything works and comes together. mayby one day im usefull enough to contribute. but still in a learning procces that is why it may seems like dumb questions.

you'r absolutely right, i looked it up and really does use connection tracking, except the "easy" coding of nftables and way less code, and its old, but why we going to use nftables?

yes, thats true but how does your firewall looks like? how do you make a safe zone for devices that you dont trust (in .config format please)

And the past couple of hours i was trying to understand and adjust the openwrt iptables and lost a lot of time because firewall builder is gui for easy adjusting iptables, found out that the developent stopped at iptables version v1.4, and openwrt 21.02.3 is using iptables v1.8.7 (and wondering why some functions just won't work). but i did it by hand and found a weird rule for the connection tracking:

-A zone_wan_input -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT

do you know what state DNAT means? google isnt very helpfull, it think it has something the do with masquerade the only states i know are
iptables:

  • INVALID
  • ESTABLISHED
  • NEW
  • RELATED

nftables:

  • new
  • established
  • related
  • invalid
  • untracked

I also have translated the iptables i use now (default for the apu2) to nftables, its way more expandable than iptables rule by rule.
The iptables rules:

# Generated by iptables-save v1.8.7 on Tue May 17 18:49:38 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:forwarding_lan_rule - [0:0]
:forwarding_rule - [0:0]
:forwarding_wan_rule - [0:0]
:input_lan_rule - [0:0]
:input_rule - [0:0]
:input_wan_rule - [0:0]
:output_lan_rule - [0:0]
:output_rule - [0:0]
:output_wan_rule - [0:0]
:reject - [0:0]
:syn_flood - [0:0]
:zone_lan_dest_ACCEPT - [0:0]
:zone_lan_forward - [0:0]
:zone_lan_input - [0:0]
:zone_lan_output - [0:0]
:zone_lan_src_ACCEPT - [0:0]
:zone_wan_dest_ACCEPT - [0:0]
:zone_wan_dest_REJECT - [0:0]
:zone_wan_forward - [0:0]
:zone_wan_input - [0:0]
:zone_wan_output - [0:0]
:zone_wan_src_REJECT - [0:0]


#input
#loopback -> firewall accept
-A INPUT -i lo -m comment --comment "!fw3" -j ACCEPT

-A INPUT -m comment --comment "!fw3: Custom input rule chain" -j input_rule
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "!fw3" -j syn_flood

#br-lan -> firewall goto zone_lan_input
-A INPUT -i br-lan -m comment --comment "!fw3" -j zone_lan_input
#eth0.300 -> firewall goto zone_lan_input
-A INPUT -i eth0.300 -m comment --comment "!fw3" -j zone_wan_input


#forwarding
-A FORWARD -m comment --comment "!fw3: Custom forwarding rule chain" -j forwarding_rule
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT

#br-lan -> outgoing diff host goto zone_lan_forward
-A FORWARD -i br-lan -m comment --comment "!fw3" -j zone_lan_forward
#eth0.300 -> outgoing diff host goto zone_wan_forward
-A FORWARD -i eth0.300 -m comment --comment "!fw3" -j zone_wan_forward

-A FORWARD -m comment --comment "!fw3" -j reject


#output
#router -> loopback accept
-A OUTPUT -o lo -m comment --comment "!fw3" -j ACCEPT

-A OUTPUT -m comment --comment "!fw3: Custom output rule chain" -j output_rule
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT

#router -> br-lan goto zone_lan_output
-A OUTPUT -o br-lan -m comment --comment "!fw3" -j zone_lan_output
#router -> eth0.300 goto zone_wan_output
-A OUTPUT -o eth0.300 -m comment --comment "!fw3" -j zone_wan_output


#some stateless rules
-A reject -p tcp -m comment --comment "!fw3" -j REJECT --reject-with tcp-reset
-A reject -m comment --comment "!fw3" -j REJECT --reject-with icmp-port-unreachable
-A syn_flood -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 25/sec --limit-burst 50 -m comment --comment "!fw3" -j RETURN
-A syn_flood -m comment --comment "!fw3" -j DROP

#references
-A zone_lan_dest_ACCEPT -o br-lan -m comment --comment "!fw3" -j ACCEPT

#if the br-lan goes to a diff host goto emty chain and else if the connection state is not invalid accept the connection if the output interface is eth0.300 or br-lan
-A zone_lan_forward -m comment --comment "!fw3: Custom lan forwarding rule chain" -j forwarding_lan_rule
-A zone_lan_forward -m comment --comment "!fw3: Zone lan to wan forwarding policy" -j zone_wan_dest_ACCEPT
##accept if the connection status is DNAT?
-A zone_lan_forward -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT
-A zone_lan_forward -m comment --comment "!fw3" -j zone_lan_dest_ACCEPT

#br-lan -> firewall empty chain if the input interface is br-lan and connection status is NEW and UNTRACKED  or output interface is br-lan accept the connection
-A zone_lan_input -m comment --comment "!fw3: Custom lan input rule chain" -j input_lan_rule
##accept if the connection status is DNAT?
-A zone_lan_input -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT
-A zone_lan_input -m comment --comment "!fw3" -j zone_lan_src_ACCEPT

-A zone_lan_output -m comment --comment "!fw3: Custom lan output rule chain" -j output_lan_rule
-A zone_lan_output -m comment --comment "!fw3" -j zone_lan_dest_ACCEPT


#references
-A zone_lan_src_ACCEPT -i br-lan -m conntrack --ctstate NEW,UNTRACKED -m comment --comment "!fw3" -j ACCEPT
-A zone_wan_dest_ACCEPT -o eth0.300 -m conntrack --ctstate INVALID -m comment --comment "!fw3: Prevent NAT leakage" -j DROP
-A zone_wan_dest_ACCEPT -o eth0.300 -m comment --comment "!fw3" -j ACCEPT
-A zone_wan_dest_REJECT -o eth0.300 -m comment --comment "!fw3" -j reject


#eth0.300 to a different host empty chain if protocol is esp and output interface is br-lan accept, if protocol is udp with destination port 500 and output interface br-lan accept, if output interface is eth0.300 reject the connection.
-A zone_wan_forward -m comment --comment "!fw3: Custom wan forwarding rule chain" -j forwarding_wan_rule
-A zone_wan_forward -p esp -m comment --comment "!fw3: Allow-IPSec-ESP" -j zone_lan_dest_ACCEPT
-A zone_wan_forward -p udp -m udp --dport 500 -m comment --comment "!fw3: Allow-ISAKMP" -j zone_lan_dest_ACCEPT
##accept if the connection status is DNAT?
-A zone_wan_forward -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT
-A zone_wan_forward -m comment --comment "!fw3" -j zone_wan_dest_REJECT


#eth0.300 -> firewall (all incomming trafic) empty chain, if protocol is udp and destination port is 68 accept, if protocol is icmp with icmp-type8 accept, if protocol igmp accept, if input interface is eth0.300 reject the connection thats why this chain is called so reject everything else
-A zone_wan_input -m comment --comment "!fw3: Custom wan input rule chain" -j input_wan_rule
-A zone_wan_input -p udp -m udp --dport 68 -m comment --comment "!fw3: Allow-DHCP-Renew" -j ACCEPT
-A zone_wan_input -p icmp -m icmp --icmp-type 8 -m comment --comment "!fw3: Allow-Ping" -j ACCEPT
-A zone_wan_input -p igmp -m comment --comment "!fw3: Allow-IGMP" -j ACCEPT
##accept if the connection status is DNAT?
-A zone_wan_input -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT
-A zone_wan_input -m comment --comment "!fw3" -j zone_wan_src_REJECT


#firewall -> eth0.300 (so going outside to the internet) if the output inerface is eth0.300 accept except if the connection state is INVALID then drop the connection
-A zone_wan_output -m comment --comment "!fw3: Custom wan output rule chain" -j output_wan_rule
-A zone_wan_output -m comment --comment "!fw3" -j zone_wan_dest_ACCEPT

#redirections
-A zone_wan_src_REJECT -i eth0.300 -m comment --comment "!fw3" -j reject
COMMIT
# Completed on Tue May 17 18:49:38 2022

same rules nftables:

#remove every ruleset and build new ruleset
flush ruleset


#start ipv4/ipv6 filter
table inet filter{

	#input every packet that received by the router drop the connection if there isnt a exeption
	chain input {
        type filter hook input priority 0; policy drop;
		#accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }

        #drop connections that arn't comming from the loopback
        iif != lo ip daddr 127.0.0.1/8 counter drop comment "drop connections to loopback not coming from loopback"
		iif != lo ip6 daddr ::1/128 counter drop comment "drop connections to loopback not coming from loopback"


        # allow loopback traffic, anything else jump to chain for further evaluation
        iifname vmap { lo : accept, br-lan : jump zone_lan_input, eth0.300 : jump zone_wan_input}
        }


	    #Everything that being transmited trough the router to a differnt host. drop the connection if there isnt a exeption
        chain forward {
		type filter hook forward priority 0; policy drop;

		#accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }


        #Every interface that needs special rules before going to the internet
        iifname vmap {eth0.300 : jump zone_wan_forward}
		meta iifname . meta oifname {br-lan . eth0.300, br-lan . br-lan} accept
        }


        #Everything that being transmited by the router
	    chain output {
		type filter hook output priority 0; policy accept;
        #accept own created connections drop everything else
        ct state vmap { established : accept, related : accept, invalid : drop }

		}

	#the nat masquerade to hide every ip address ipv4 and ipv6
	chain postrouting {
	type nat hook postrouting priority 100; policy accept;

        #masquerade private IP addresses ipv4
        oifname $wan4 masquerade
        #masquerade private IP addresses ipv6
        oifname $wan6 masquerade
    }

#chains input
chain zone_lan_input {
#input interface is already br-lan so this works
ct state vmap { new : accept, untracked : accept }
}

chain zone_wan_input {
#if protocol is udp and destination port is 68 accept, if protocol is icmp with icmp-type8 accept, if protocol igmp accept
ip protocol . th dport vmap { udp . 68 : accept}
#ping with flood protection
ip protocol icmp accept_icmp_v4 limit rate 1/second accept
ip6 nexthdr icmpv6 accept_icmp_v6 limit rate 1/second accept
#igmp is only ipv4
ip protocol igmp accept
#letting the connection easy down
reject
}


#chains forwarding

chain zone_wan_forward {
#easy expandable
ip protocol . th dport vmap { udp . 500 : accept}
ip protocol esp accept
#letting the connection easy down
reject
}
}

OpenWRT, if you build it with nftables support (as is the default now), creates all required nftable rules. You've still not explained why you're trying to manually edit the firewall rules, rather than just using luci or UCI on the command line and allowing OpenWRT to convert that config to the required rules.

If you want a secure network then trying to write the firewall rules by hand (when you've admitted you have next to no knowledge of what you're doing) is not the way to go about it.

1 Like

fw3(iptables) is default in the master branch, now the master branch can be build or opkg installed with fw4(nftables).

There is no GUI for fw4 (yet) inside luci/UCI. But fw4 gonna become the standard firewall and if I learn nftables now I don't need to re-learn and rebuild the my whole firewall if fw4 becomes the standard. So it's logical to start early.

Also Iast month I builded a new openwrt image to enable crypto (i had a lot of CPU errors for some reason) and update the bios from openwrt. After I was done updating reloaded the original kernel (because a altered kernel create a different .vertimagic that doesn't allow kmod updates). Found out that git repository's arnt that easy, and that the CPU errors came from the inter ax200 that doesn't support AP mode (I'm really stubborn and spend hours upon hours to make the AP mode working, that's time i not getting back ending up ordering two new pcie cards that support wave 2 and ax in AP mode).

But after this fresh install i thought I start over with everything I learned past couple of months it must be easier and better than before. In the last build i separated the servers from the main wifi and lan. But I couldn't get to the servers trough the ddns only if I forwarded the server trough the subnet and back they could be reached by a internal IP address. Read a lot about AAAAAA DNS etc. But never got it working (sometimes it did but then I couldn't reach the internet.)

Last week I read about the connection states and you can easy connect two interfaces to each other one-way.
So like a ranked DMZ network 5 can call everything. 4 can call 3,2,1. 3 can call 2 and 1. 2 can call 1.

I thought I give it a shot :grin:

Incorrect, fw4 has been default in master (and openwrt-22.03) for a few months now.

Incorrect, luci supports fw4 just fine since day-one of the switch - it uses the same on-flash configuration file/ syntax as fw3 (/etc/config/firwarewall).

3 Likes

Than I have something messed up when building the openwrt img.

This was really unnecessary and a waist of time, sorry and thanks :+1:

didnt get nftables working when building an image, ending up flashing the latest stable 21.3 RC1 image.
where fw4 starting being the default (tested 21.02.3 but only iptables installed).
cant find the real fw3/4 difference only in the sites below that

OpenWrt currently uses fw3 to set the firewall, and that is not compatible with nftables

info: https://openwrt.org/docs/guide-user/firewall/filtering_traffic_at_ip_addresses_by_dns

and if you follow this guide: https://openwrt.org/docs/guide-user/firewall/misc/nftables in the openwrt version 21.02.3 nft your firewall messed up because of missing files for the nftables.

but thanks for the tip

You are mixing the old stable 21.02.3 (with iptables) and the new 22.03.0-rc1 (with nftables).

21.02 branch had iptables.
22.03 and the development master have nftables.

1 Like