It appears that there is still a bug in the checksum correction
of ICMP packets which return through a NAT machine in response to
an earlier sent out UDP packet from inside. The setup is a follows:

 inside box                 NAT box              internet
------------------------------------------------------------
192.168.128.2 ---- 192.168.128.1|public_ip ---- 80.81.31.28

All machines run FreeBSD 4.10-STABLE (using the recently
committed ipfilter-3.4.35).

192.168.128.2 does a "echo | nc -u 80.81.31.28 54321". Since
nothing listens on port 54321, 80.81.31.28 sends back an ICMP
packet type 3/3. Running ethereal on the inside wire we can
capture this packet:

Frame 2 (70 bytes on wire, 70 bytes captured)
Ethernet II, Src: 00:02:b3:1f:25:dc, Dst: 00:e0:18:98:46:ef
Internet Protocol, Src Addr: 80.81.31.28 (80.81.31.28), Dst Addr: 192.168.128.2 
(192.168.128.2)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
    Total Length: 56
    Identification: 0xab72
    Flags: 0x00
    Fragment offset: 0
    Time to live: 55
    Protocol: ICMP (0x01)
    Header checksum: 0x283b (correct)
    Source: 80.81.31.28 (80.81.31.28)
    Destination: 192.168.128.2 (192.168.128.2)
Internet Control Message Protocol
    Type: 3 (Destination unreachable)
    Code: 3 (Port unreachable)
    Checksum: 0x23b3 (incorrect, should be 0x9a4c)
XXX ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Internet Protocol, Src Addr: 192.168.128.2 (192.168.128.2), Dst Addr: 80.81.31.28 
(80.81.31.28)
        Version: 4
        Header length: 20 bytes
        Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
        Total Length: 7424
        Identification: 0xab72
        Flags: 0x00
        Fragment offset: 0
        Time to live: 54
        Protocol: UDP (0x11)
        Header checksum: 0x2946 (incorrect, should be 0x0c63)
        Source: 192.168.128.2 (192.168.128.2)
        Destination: 80.81.31.28 (80.81.31.28)
    User Datagram Protocol, Src Port: 2723 (2723), Dst Port: 54321 (54321)
        Source port: 2723 (2723)
        Destination port: 54321 (54321)
        Length: 9
        Checksum: 0x66ef


The checksum in questions is marked with XXX. The problem happens
only if the source port was changed by the NAT box due to the

  map tun0 192.168.128.0/24  -> 0/32  portmap tcp/udp 32768:65000

line. If we remove the "portmap ..." option, the ICMP packets won't
have the checksum error and nc will quit immediately. I assmue that
ip_nat.c doesn't take the changed port properly into account when
recalculating the checksum of the "inner" ICMP packet.

Everything worked before 3.4.35 was MFC'ed to FreeBSD 4.10-STABLE.

The problems also mainfests when doing a traceroute from the inner
box to the outer world as the resulting ICMP packets won't get
back properly.

Anybody seeing similar things?

Thanks,

        -Andre

Reply via email to