kern/181690: patch that fix pf "NAT proxy port allocation"
Olivier Cochard-Labbe
olivier at cochard.me
Fri Aug 30 19:00:00 UTC 2013
>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 at 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:
More information about the freebsd-bugs
mailing list