NAT fails to correctly translate udp port numbers embedded in certain ICMP error packets

Daniel Haid d.haid at gogi.tv
Sat Apr 18 19:06:32 UTC 2015


Hi,

I think I found a bug in the NAT of the packet filter, but I am not sure. My
setup is as follows.

client (linux)
  |
  | bridge0, mtu=1500
  |
pfsense 2.2.2 (FreeBSD 10.1-RELEASE-p9)
  |
  | pppoe0, mtu=1492
  |
internet

On the client, I run the following command:

# nping --udp 8.8.8.8 -g 10000 -p 20000 --data-length 1472 --df

This generates five UDP packets of IP length 1500, set the do not fragment
option, and send them from source port 10000 to destination port 20000. I have
verified by packet capture that this really happens.

As the mtu of the pppoe link is 1492, the packets cannot reach their
destination, so pfsense generates "ICMP fragmentation needed" error packets. I
expect five such packets, and I indeed receive five, but the first one (!)
seems to be corrupted, as I will now explain.

I run the following command (with following output) on pfsense:

# pfctl -s state | grep 10000
bridge0 udp 8.8.8.8:20000 <- 10.0.0.101:10000       NO_TRAFFIC:SINGLE
pppoe0 udp 84.112.84.112:59518 (10.0.0.101:10000) -> 8.8.8.8:20000       SINGLE:NO_TRAFFIC

Each of the five ICMP packets should have embedded the header of the respective
offending 1500-byte packet. The NAT should appropriately map the port numbers.
However, the first packet receieved from the client has source port 59518
(the untranslated one) in the UDP header embedded in the ICMP packet.
The other four ICMP packets are fine (source port 10000, which is the correct,
translated, value).

Note that this only happens for ICMP error packets originating at the pfsense
router itself. ICMP error packets of the same type but from a router in the
public internet are always translated correctly (all five!) before being
forwarded to the client.

For reference, I have added the output of pfctl -s nat below.

--DH

no nat proto carp all
nat-anchor "natearly/*" all
nat-anchor "natrules/*" all
nat on pppoe0 inet from 127.0.0.0/8 to any port = isakmp -> 84.112.84.112 static-port
nat on pppoe0 inet from 10.0.0.0/24 to any port = isakmp -> 84.112.84.112 static-port
nat on pppoe0 inet from 127.0.0.0/8 to any -> 84.112.84.112 port 1024:65535
nat on pppoe0 inet from 10.0.0.0/24 to any -> 84.112.84.112 port 1024:65535
no rdr proto carp all
rdr-anchor "relayd/*" all
rdr-anchor "tftp-proxy/*" all
rdr-anchor "miniupnpd" all


More information about the freebsd-pf mailing list