Fw4: zone-specific DROP rule with log limits enabled logs traffic to other zones

A firewall rule configured to DROP and LOG with limits from LAN to WAN also logs traffic destined to other zones, even though that traffic is not dropped and should not match the rule’s destination zone.
The DROP behavior is correct, but logging is applied without destination zone constraints, producing misleading logs.

Example rule:

config rule
option name 'testlog'
option src 'lan'
list src_ip '192.168.5.5'
option dest 'wan'
option target 'DROP'
list proto 'tcp'
option dest_port '80'
option log '1'
option log_limit '1/s'

Test setup:

  • eth0 lan 192.168.5.0/24
  • eth1 lan2 172.25.5.0/24
  • eth2 wan

From host 192.168.5.5:

  • Connect to a WAN address:

    nc -v -w 1 1.1.1.1 80
    
  • Connect to a LAN2 address (there's a web server running on 172.25.5.13):

    nc -v -w 1 172.25.5.13 80
    

Result:

  • Traffic to WAN is dropped and logged as expected
  • Traffic to LAN2 is not dropped (as expected) but logged (unexpected)

Example log (redacted for readability):

kernel: [5460890.535892] testlog: IN=eth0 OUT=eth1 SRC=192.168.5.5 DST=172.25.5.13 DPT=80

Generated rules in forward_lan:

ip saddr 192.168.5.5 tcp dport 80 limit rate 1/second burst 5 packets log prefix "testlog: "
ip saddr 192.168.5.5 tcp dport 80 jump drop_to_wan

Reproduced in 24.10 and 25.12, x86_64.

There's not much you can do. Both rules will apply to packets entering through the lan interface, but the DROP target will only apply to packets leaving the wan interface.

If you're looking for a workaround, rather than just asking why is that, you can exclude RFC1918 addresses from the equation

config rule
        list src_ip '192.168.5.5'
        list dest_ip '!10.0.0.0/8'
        list dest_ip '!172.16.0.0/12'
        list dest_ip '!192.168.0.0/16'
	    ...

or create a custom firewall rule.

I was looking at the history of this log_limit implementation and found an interesting reference to anonymous chains. I had no idea this is a valid syntax today in nftables:

ip saddr 192.168.5.5 tcp dport 80 goto {
        oifname != "wan" return
        limit rate 1/second burst 5 packets log prefix "testlog: "
        drop
}

This was something @jow alluded to in the PR, but the final implementation was slightly different in nftables 0.9.7 (and called "implicit chains").

My example isn't worth much, but I think it is compelling for these complicated cases of multiple actions in a rule. The goto can also be jump, depending whether you want to continue processing in the base chain.

Also pinging @luizluca who wrote the original log_limit.

1 Like

You can track events with conntrack.