Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Oct 2018 00:26:44 +0200
From:      Andreas Longwitz <longwitz@incore.de>
To:        freebsd-pf@freebsd.org
Subject:   rdr pass for proto tcp sometimes creates states with expire time zero and so breaking connections 
Message-ID:  <5BC51424.5000309@incore.de>

next in thread | raw e-mail | index | archive | help
On two of my FreeBSD 10 (r338093) firewall servers some incoming ssh
connections stopped to work because pf started to create states with
expire time zero (instead of 86400 sec) for translation statements like

rdr pass on em0 proto tcp from any to myip port 8022 --> 10.0.0.254

Therefore a command given on a remote server like

           ssh -p 8022 myip sleep 15

did not return, because the created state for the connection was purged
by pf (interval 10 sec) before 15 seconds. If I replace the rdr pass
rule with a rdr rule and a separate filter pass rule then the created
state always has expire time 24h and everything is ok.

I have tried to analyze the bug in the rdr pass rule. Immediately after
starting the above ssh command on the remote sever I see with pfctl -vss
the sreated state on my firewall machine:

all tcp 10.0.0.254:8022 (myip:8022) <- remoteip:59233
ESTABLISHED:ESTABLISHED
   [1443872812 + 66608] wscale 6  [1365307391 + 66560] wscale 3
   age 00:00:00, expires in 00:00:00, 13:12 pkts, 2955:3306 bytes

and a DTrace script running at the same time gives

  3  19323        pfsync_state_export:entry
            creation=4491391. expire=4491391, state_timeout=2
  3  16459           pf_state_expires:entry         state_timeout=86400,
            start_timeout=6000, end_timeout=12000 states=882
  3  17624          counter_u64_fetch:entry
  3  17625         counter_u64_fetch:return
            returncode (states_cur)=4294967248 = 0xffffffd0
  3  16460          pf_state_expires:return
            returncode=4491391
  3  19324       pfsync_state_export:return
            creation=0. expire=0, syncstate_timeout=2
  0  12730                   pfioctl:return
            returncode=0, time_uptime=4491391

So pf_state_expires() returns the value time_update and therefore
pfsync_state_export() gives expire zero. Reason for this is the very big
(means negative) value returned by the function counter_u64_fetch() for
states_cur. This variable is of type uint64_t and only incremented and
decremented by the macros STATE_INC_COUNTERS and STATE_DEC_COUNTERS.

I see two possibilities: Maybe counter(9) is broken for my hardware
(i386, cpu_feature=0xbfebfbff) or STATE_DEC_COUNTERS sometimes is called
 without STATE_INC_COUNTERS called before. In the above example the
value of states_cur is 1 on a fresh booted system, so we may have a
difference of 49 in calls of the COUNTER macros. I see the same number
49 in the output of pfctl -si in the line for short packets. This may be
a hint or its random.


-- 
Andreas Longwitz




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