firewall4 icon indicating copy to clipboard operation
firewall4 copied to clipboard

fw4 generates incorrect NAT leakage rule (ct state invalid instead of new) in accept_to_wan

Open fonoirs opened this issue 8 months ago • 7 comments

OpenWrt Version: 24.10.1 (r28597-0425664679) firewall4 Version: 2024.12.18~18fc0ead-r1 Target: x86_64

Observed behavior:

The default fw4 ruleset in accept_to_wan contains: meta nfproto ipv4 oifname "eth1" ct state invalid drop comment "!fw4: Prevent NAT leakage"

However, this rule does not drop new outgoing connections that leak private IPs when masquerading is missing.

Expected behavior:

It should insert the following rule instead: meta nfproto ipv4 oifname "eth1" ct state new drop comment "!fw4: Prevent NAT leakage"

Workaround:

Manually inserting the above ct state new drop rule into the accept_to_wan chain solves the problem and correctly drops un-NATed new traffic.

Please confirm whether this is a regression or a logic oversight in rule generation.

Thank you!

fonoirs avatar Jun 25 '25 00:06 fonoirs

Default does not drop packets in invalid state. Invalid state packets are not ones from misconfiguration. If you configure network routing all states are valid again without special attention to bcp38 et al.

Could you diff your /etc/config/firewall to /rom/etc/config/firewall and the rules appearing from your changes?

brada4 avatar Jun 25 '25 03:06 brada4

ct state invalid is marked when packet enters conntrack, but you can log detected invalid packets exitting system by adding something.nft in /etc/nftables.d/

chain invalid_egress {
  type filter hook postrouting priority 32768
  ct state invalid counter log
}

chain invalid_input {
  type filter hook input priority 32768
  ct state invalid counter log
}

it is last points conntrack sees the packet, after all nat conversions are done. one is exitting towards wires, other is exitting towards router itself. run nmap -A to generate conntrack-invalid packets.

input (in the view of conntrack) can be logged via sysctl net.netfilter.nf_conntrack_log_invalid=255 (dont save it in sysctl.conf, under quite general network glitches you will get unmanageable volume of logs)

brada4 avatar Jun 25 '25 10:06 brada4

Thank you for the detailed explanation — that helped clarify the purpose of the ct state invalid rule.

Just to note: I’m running OpenWrt on x86-64 with an ext4 root filesystem, so there is no /rom directory to compare against. However, I haven’t modified the default firewall configuration beyond enabling LAN-to-WAN forwarding and masquerade. The behavior I'm seeing occurs even on a clean, freshly built image from the same build environment.

Through testing, I found that the ct state invalid rule in accept_to_wan does not drop new outbound packets when masquerade is missing or disabled. These packets still leave the WAN interface with the original LAN source IP — they are not NATed, yet they are also not marked invalid, so the current rule doesn’t block them.

When I manually added a rule like:

meta nfproto ipv4 oifname "eth1" ct state new drop

It correctly blocked those un-NATed new connections, fulfilling the goal of preventing NAT leakage.

So it seems the current ct state invalid rule does not cover this case. Would it make sense for fw4 to optionally include a ct state new drop rule in accept_to_wan, or expose a flag to enable stricter NAT enforcement? Below is /etc/config/firewall:

config defaults
	option syn_flood '1'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'

config zone
	option name 'lan'
	list network 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'

config zone
	option name 'wan'
	list network 'wan'
	list network 'wan6'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'

config forwarding
	option src 'lan'
	option dest 'wan'

fonoirs avatar Jun 25 '25 14:06 fonoirs

Your ruleset is heavily modified, but no dropping of invalid packets is enabled. Could you compare conf to one found in this repo?

brada4 avatar Jun 25 '25 15:06 brada4

I think i am getting it. wan zone drops invalid exitting packets. That is the default inherited from masq checkbox. "drop new" would block router from internet access, and there is no rules allowing output. That would be a heavy feat making those. That default would disable itself if you uncheck masquerade. And it is not to drop misconfiguration packets, but exactly what nftables conntrack deems invalid to process.

brada4 avatar Jun 25 '25 15:06 brada4

The code for this rule is located here: root/usr/share/firewall4/templates/zone-drop-invalid.uc

Here’s the background: I’ve been evaluating an upgrade of my system from OpenWrt 21 to OpenWrt 24. Since my setup relies on the firewall, I needed to research FW4 in advance. Unlike FW3, FW4 is based on nftables.

FW4 and nftables are amazing — I think I’m in love with them.

I discovered that in the world of FW4 and nftables, NAT and forwarding are decoupled, which is a very clean design.

Of course, I need masquerading. After enabling masquerade, I noticed a rule was added in the accept_to_wan chain:

meta nfproto ipv4 oifname "eth1" ct state invalid counter drop comment "!fw4: Prevent NAT leakage"

This is great — if someone mistakenly deletes the masquerade rule, it would prevent IPs from the LAN from being sent out via WAN. But in reality, this doesn't work. I tried deleting the masquerade rule — and sure enough, LAN-originated packets still went out through WAN.

If no one deletes the masquerade rule, there’s no problem. But the behavior of this "Prevent NAT leakage" rule is not what I expected.

fonoirs avatar Jun 25 '25 16:06 fonoirs

No NAT no NAT leakage, just routing as you configured. Anything catches in the last call rules? It is just flat routing without nat, no special masquerade magic involved.

brada4 avatar Jun 25 '25 17:06 brada4