IPFW keep-state and in-kernel NAT exposes local ip on external interface

On FreeBSD 10.1p13 with two interfaces em0(internet) and em1(lan) I can fish (tcpdump)packets on em0 which have escaped the in-kernel NAT and have as source address an IP on the LAN.

This should not happen and I can confirm that with pf this is not the case.

ipfw rules:
Code:
ipfw nat 123 config ip xxx.xxx.xxx.xxx same_ports reset

00100 reass ip from any to any in
00200 allow ip from any to any via lo0
00300 allow ip from any to any via em1
00400 nat 123 ip from any to any in recv em0
00500 check-state
00600 skipto 24000 ip from any to me dst-port 80,443,22,500,4500,1194,993,8112 in recv em0 keep-state
00700 skipto 24000 ip from any to any out xmit em0 keep-state
00800 deny log ip from any to any
24000 nat 123 ip from any to any out xmit em0
24100 allow ip from any to any

Why is this happening?
 
I think I resolved this.
Contrary to many online tutorials, including the example of the handbook regarding NAT (https://www.freebsd.org/doc/handbook/firewalls-ipfw.html), when one places the NAT rules with the opposite order (i.e. outbound rule first and then the inbound rule) the problem disappears.

Code:
ipfw nat 123 config ip xxx.xxx.xxx.xxx same_ports reset

00100 reass ip from any to any in
00200 allow ip from any to any via lo0
00300 allow ip from any to any via em1
00400 nat 123 ip from any to any out xmit em0
00500 check-state
00600 skipto 24000 ip from any to me dst-port 80,443,22,500,4500,1194,993,8112 in recv em0 keep-state
00700 skipto 24000 ip from any to any out xmit em0 keep-state
00800 deny log ip from any to any
24000 nat 123 ip from any to any in recv em0
24100 allow ip from any to any
 
Thanks. I posted it in the freebsd-ipfw mailing list to see if someone of the devs has any objections to reversing the order. I will file the PR if no objections arise.
 
This is definitely a bug and it is not resolved. Thus I removed the [solved] prefix. See PR 201590.
It has to do with the keepalives ip_fw_dynamic.c sends, they do not go through NAT.
Setting sysctl net.inet.ip.fw.dyn_keepalive=0 resolves the symptoms but not the cause.
 
Last edited by a moderator:
Back
Top