Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Jun 2013 08:10:01 GMT
From:      Paul Guyot <paul@semiocast.com>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/179392: [pf] [ip6] Incorrect TCP checksums in rdr return packets
Message-ID:  <201306070810.r578A16J072183@megaptera.semiocast.net>
Resent-Message-ID: <201306070820.r578K3Jp068583@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         179392
>Category:       kern
>Synopsis:       [pf] [ip6] Incorrect TCP checksums in rdr return packets
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 07 08:20:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Paul Guyot
>Release:        FreeBSD 9.1-RELEASE amd64
>Organization:
Semiocast
>Environment:
System: FreeBSD megaptera.semiocast.net 9.1-RELEASE FreeBSD 9.1-RELEASE #1 r250855M: Tue May 21 15:14:41 UTC 2013 root@megaptera.semiocast.net:/usr/obj/usr/src/sys/GENERIC amd64

Also happens on:
FreeBSD fangsiao.semiocast.net 9.1-PRERELEASE FreeBSD 9.1-PRERELEASE #0: Sat Nov 17 23:54:19 UTC 2012     root@fangsiao.semiocast.net:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
PF incorrectly computes the checksum of IPv6 TCP packets that it rewrites as part of a simple rdr rule that just changes the port number. Maybe it just does not update the checksum...

The following IPv4 rule works properly:
rdr pass inet proto tcp from any to 188.165.36.95 port 443 -> 188.165.36.95 port 8443

The following IPv6 rule does not work:
rdr pass inet6 proto tcp from any to 2001:41d0:8:8822::1 port 443 -> 2001:41d0:8:8822::1 port 8443

Ports redirection happens properly, but on their way out, packets do not have the proper checksum and are eventually dropped by the client. Since this happens during TCP connection handshake, the only rewritten packets on their way out are SYN, ACK.

This happens with and without scrub rules.

The problem, or a similar problem, is discussed on mailing lists. Yet no PR seems to have been filed, probably because it was insufficiently documented.

In both threads, it is linked with jails as jails are one of the use-case of rdr/nat with IPv6 :
http://lists.freebsd.org/pipermail/freebsd-stable/2012-July/068987.html
http://lists.freebsd.org/pipermail/freebsd-pf/2012-August/006710.html

and
http://lists.freebsd.org/pipermail/freebsd-pf/2012-December/006916.html

Also, this bug might or might not be related to kern/172648 or kern/171733

However, unlike kern/172648, this bug has no known workaround. Indeed, the problem here is to be able to rewrite incoming packets on a privileged port and forward them to a local server, then get the response from the local server and forward it to the client after rewriting the source port.

>How-To-Repeat:
Create a simple rdr rule on IPv6 and let everything else pass.

rdr pass inet6 proto tcp from any to [IPv6 External IP] port 443 -> [IPv6 External IP] port 8443

Start a server on this port, for example with nc.
Try to connect from outside on port 8443. It should work.
Restart nc. Try to connect from outside port 443. The client will eventually timeout.

Eventually, use tcpdump to record the packets and notice the checksums are incorrect on received SYN, ACK packets from port 443.

>Fix:

	


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306070810.r578A16J072183>