Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Aug 2013 18:54:32 GMT
From:      Olivier Cochard-Labbe <olivier@cochard.me>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/181690: patch that fix pf "NAT proxy port allocation"
Message-ID:  <201308301854.r7UIsWxe063549@oldred.freebsd.org>
Resent-Message-ID: <201308301900.r7UJ00P8098135@freefall.freebsd.org>

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

>Number:         181690
>Category:       kern
>Synopsis:       patch that fix pf "NAT proxy port allocation"
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Aug 30 19:00:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Olivier Cochard-Labbe
>Release:        9.2-RC3
>Organization:
BSD Router Project
>Environment:
FreeBSD bsdrp2.orange.bsdrp.net 9.2-RC3 FreeBSD 9.2-RC3 #0 r255043M: Fri Aug 30 18:57:21 CEST 2013     root@orange.bsdrp.net:/usr/obj/BSDRP.amd64/usr/local/BSDRP/BSDRP/FreeBSD/src/sys/amd64  amd64
>Description:
I've got some UDP packet loss with pf configured with NAT.

Here is my pf.conf:
ext_if = "igb3"
set skip on lo0
set debug loud
nat on $ext_if inet from any to any -> $ext_if port 50000:50003
pass

=> The NAT range port is limited to 4 port for an easy reproduction of this problem.

Then I generate 4 parallel UDP flow (with 4 netblast), but when I start the 3th flow I've got theses log message:
kernel: pf: wire key attach failed on all: UDP out wire: 2.2.2.3:4123 2.2.2.2:50003 1:0, existing: UDP out wire: 2.2.2.3:4123 2.2.2.2
kernel: :50003 stack: 2.2.2.3:4123 1.1.1.1:39749 1:0

I've found this same error message regarding OpenBSD 4.6 here:
http://openbsd.7691.n7.nabble.com/kernel-6300-PF-NAT-UDP-port-reuse-wire-key-attach-failed-td195274.html

>From this thread, it seems that "pf_get_sport() was failing to notice that the ports were in-use" and there is a proposed patch.
I've adapted this patch to FreeBSD (9.2) and do a try: No more "wire key attach failed", I've got this message in place:
Aug 30 19:40:37 bsdrp2 kernel: pf: NAT proxy port allocation (50000-50003) failed

Regards
>How-To-Repeat:
Use the pf.conf example file given on my full description, and try to generate more than 3 or 4 UDP flows that match the NAT condition.

>Fix:
By applying this patch.
But Warning: I didn't have any idea of what exactly this patch do!!!
I've just did a "dummy" adaptation and it magically works :-)

Patch attached with submission follows:

Index: sys/contrib/pf/net/pf_lb.c
===================================================================
--- sys/contrib/pf/net/pf_lb.c	(revision 255043)
+++ sys/contrib/pf/net/pf_lb.c	(working copy)
@@ -338,9 +338,9 @@
 	do {
 		key.af = af;
 		key.proto = proto;
-		PF_ACPY(&key.addr[1], daddr, key.af);
-		PF_ACPY(&key.addr[0], naddr, key.af);
-		key.port[1] = dport;
+		PF_ACPY(&key.addr[0], daddr, key.af);
+		PF_ACPY(&key.addr[1], naddr, key.af);
+		key.port[0] = dport;
 
 		/*
 		 * port search; start random, step;
@@ -349,11 +349,11 @@
 		if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
 		    proto == IPPROTO_ICMP)) {
 			key.port[0] = dport;
-			if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+			if (pf_find_state_all(&key, PF_OUT, NULL) == NULL)
 				return (0);
 		} else if (low == 0 && high == 0) {
 			key.port[0] = *nport;
-			if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+			if (pf_find_state_all(&key, PF_OUT, NULL) == NULL)
 				return (0);
 		} else if (low == high) {
 			key.port[0] = htons(low);
@@ -377,7 +377,7 @@
 #endif
 			/* low <= cut <= high */
 			for (tmp = cut; tmp <= high; ++(tmp)) {
-				key.port[0] = htons(tmp);
+				key.port[1] = htons(tmp);
 				if (pf_find_state_all(&key, PF_IN, NULL) ==
 #ifdef __FreeBSD__
 				    NULL) {
@@ -389,7 +389,7 @@
 				}
 			}
 			for (tmp = cut - 1; tmp >= low; --(tmp)) {
-				key.port[0] = htons(tmp);
+				key.port[1] = htons(tmp);
 				if (pf_find_state_all(&key, PF_IN, NULL) ==
 #ifdef __FreeBSD__
 				    NULL) {


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



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