Bug 86871 - [tcp] [patch] allocation logic for PCBs in TIME_WAIT state causes packet drops on stateful FWs
Summary: [tcp] [patch] allocation logic for PCBs in TIME_WAIT state causes packet drop...
Status: Closed Feedback Timeout
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 5.4-RELEASE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-net (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-03 13:10 UTC by Vladimir Kotal
Modified: 2016-02-25 05:06 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir Kotal 2005-10-03 13:10:10 UTC
      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.

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.
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@ipfw2$ ./tcpclient-bind SERVER 21
connecting
connected
src addr = CLIENT-IP
src port = 1234
closing connection
lada@ipfw2$ netstat -an |grep SERVER-IP
tcp4       0      0  CLIENT-IP.1234     SERVER-IP.21      TIME_WAIT
lada@ipfw2$ ./tcpclient-bind SERVER 21
connecting
tcpclient-bind: connect: Operation timed out
lada@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.
Comment 1 Vladimir Kotal 2005-10-03 18:27:22 UTC
more possible solutions:

   - bind allocation of TIME_WAIT sockets to sequential/random 
allocation switch
     (when doing the transition to sequential port allocation, also make 
possible allocation of sockets in TIME_WAIT state)
    - do not (re)allocate sockets in TIME_WAIT state by default. if 
number of free ports reaches certain watermark, turn on allocation of 
sockets in TIME_WAIT state.
Comment 2 Bruce Cran freebsd_committer freebsd_triage 2009-12-27 15:32:36 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-net

Over to maintainer(s).
Comment 3 Harrison Grundy 2014-12-18 13:26:40 UTC
9 years on... does this still occur?
Comment 4 Hiren Panchasara freebsd_committer freebsd_triage 2016-02-25 05:06:49 UTC
(In reply to Harrison Grundy from comment #3)
Probably not.

Please reopen if this is still an issue on -CURRENT or stable/10.