rdr pass for proto tcp sometimes creates states with expire time zero and so breaking connections

Andreas Longwitz longwitz at incore.de
Sat Oct 27 21:48:38 UTC 2018


>     In the problem I have reported for states of "rdr pass" rules I see
>     start=6000, end=12000, timeout=86400 and (obviously erroneous, probably
>     negative) states=0xffffffd0.
> 
> I have no idea how that can happen. Just to make sure I understand: you
> know that states is negative here because of a printf() or SDT addition
> in pf_expire_states(), right?

I did not change the kernel, I use DTrace on my firewall server
fwextern. In pf.conf I have changed all productive "rdr pass" rules to a
rdr rule and an extra filter rule. Now only one "rdr pass" rule is left
for test:

  rdr pass on $if_internet proto tcp from 31.17.172.227 to $ip_internet
      port 8022 -> 10.0.0.254

Now I start the following DTrace script pfcounter.d, which will be
active when a SYN on port 8022 arrives:

#!/usr/sbin/dtrace -s

fbt::pf_normalize_tcp:entry
/((*(args[2]->m_hdr.mh_data + 33)) & 0x02) == 0x02 && htons(*(short
*)(args[2]->m_hdr.mh_data + 22)) == 8022/
       /* SYN + port 8022 */
{ self->flag1 = 1; }

fbt::pf_test:return
/self->flag1/ { self->flag1 = 0; }

fbt::pfioctl:entry
/args[1] == 3221767193 && ((struct pfioc_states *)args[2])->ps_len != 0/
       /* DIOCGETSTATES  &&  len != 0 */
{ self->flag2 = 1; }

fbt::counter_u64_fetch:entry
/self->flag2/ { }
fbt::counter_u64_fetch:return
/self->flag2/ { printf("        returncode (states_cur)=%d / 0x%x",
args[1], args[1]); }

fbt::pfioctl:return
/self->flag2/
{ self->flag2 = 0; }


Now I run on my remote test client (IP 31.17.172.227) the command

   ssh -p 8022 fwextern sleep 20

This creates on fwextern a state for the "rdr pass" rule with expire
time zero. I must be quick to run "pfctl -vss" on fwextern to see this
state and the output of the DTrace script shows me the "negative" value
of the counter:

=== root at fwextern (pts/0) -> ./pfcounter.d
dtrace: script './pfcounter.d' matched 6 probes
CPU     ID                    FUNCTION:NAME
  3  17624          counter_u64_fetch:entry
  3  17625         counter_u64_fetch:return         returncode
(states_cur)=4294967248 / 0xffffffd0

If I run on the test client the ssh command twice, then the counter is
one less negative than before:

=== root at fwextern (pts/0) -> ./pfcounter.d
dtrace: script './pfcounter.d' matched 6 probes
CPU     ID                    FUNCTION:NAME
  3  17624          counter_u64_fetch:entry
  3  17625         counter_u64_fetch:return         returncode
(states_cur)=4294967249 / 0xffffffd1
  3  17624          counter_u64_fetch:entry
  3  17625         counter_u64_fetch:return         returncode
(states_cur)=4294967249 / 0xffffffd1

Because of "sleep 20" the ssh command does not return and must be
killed. I have observed the problem on two of my firewall servers, the
pf rules never were reloaded since boot. I think there must be an
unknown event in the past, that triggered the negative counter value.

I will try to add a statement to the kernel that recognizes the problem
and go back to the "rdr pass" rules, so next time the problem occurres
we have more information than now.


Kindly regards,
Andreas



More information about the freebsd-pf mailing list