kern/86871: allocation logic for PCBs in TIME_WAIT state causes
packet drops on stateful FWs
Vladimir Kotal
vlada at devnull.cz
Mon Oct 3 05:10:19 PDT 2005
>Number: 86871
>Category: kern
>Synopsis: allocation logic for PCBs in TIME_WAIT state causes packet drops on stateful FWs
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Oct 03 12:10:10 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Vladimir Kotal
>Release: 5.4-RELEASE-p7
>Organization:
>Environment:
FreeBSD ipfw2 5.4-RELEASE-p7 FreeBSD 5.4-RELEASE-p7 #7: Mon Oct 3 11:48:16 CEST 2005 lada at ipfw2:/sys/i386/compile/GENERIC i386
>Description:
From FreeBSD 5.x on, it is possible to allocate local ports for TCP connections even if PCB for given socket is in TIME_WAIT state. This causes execessive packet drops in scenarios where client initiates lots of outgoing connections toward server with stateful firewall (pf).
This behavior is not present in 4.x releases.
>How-To-Repeat:
1. download and compile
http://techie.devnull.cz/public/tcpclient-bind.c
[ or use any other basic TCP client which can bind(2) local port ]
2. connect to TCP service running on server with stateful firewall.
3. wait for tcpclient-bind to end
4. display socket state for the connection from step nr. 2
5. connect to the same TCP service
6. watch server logs (dmesg) for 'pf BAD state' entries
For example:
lada at ipfw2$ ./tcpclient-bind SERVER 21
connecting
connected
src addr = CLIENT-IP
src port = 1234
closing connection
lada at ipfw2$ netstat -an |grep SERVER-IP
tcp4 0 0 CLIENT-IP.1234 SERVER-IP.21 TIME_WAIT
lada at ipfw2$ ./tcpclient-bind SERVER 21
connecting
tcpclient-bind: connect: Operation timed out
lada at ipfw2$
the 'BAD state' messages then look like this:
Oct 3 13:53:54 SERVER kernel: pf: BAD state: TCP SERVER-IP:21 SERVER-IP:21 CLIENT-IP:4094 [lo=1074578133 high=1074644741 win=33304 modulator=0 wscale=1] [lo=819316103 high=819382710 win=33304 modulator=0 wscale=1] 9:9 S seq=1087912989 ack=819316103 len=0 ackskew=0 pkts=12:19 dir=in,fwd
Oct 3 13:53:54 SERVER kernel: pf: State failure on: 1 | 5
example of stateful rule:
pass in quick on $ext_if proto tcp from any to ($ext_if) \
port = ftp \
flags S/S keep state \
label "EXT-ingress--ftp-cmd"
This problem is always reproducible.
One of the scenarios where this problems could manifest itself is e.g. proxy+backend setup where proxy issues big number of connections to backend server running stateful firewall.
>Fix:
There is number of possibilities:
- convert stateful firewall ruleset to stateless (really not an option in my setup)
- tweak timeouts for firewall states (also not an option)
- remove INP_TIMEWAIT logic from FreeBSD 5.x TCP stack altogether
- use following patch:
http://techie.devnull.cz/public/noTW.patch
- this patch adds new sysctl net.inet.ip.portrange.twalloc which can be used to revert the INP_TIMEWAIT behavior to the old state. the patch will preserve current bind(2)/connect(2) behavior in FreeBSD 5.x by default.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list