[pach] Reloading pf rules breaks connections on lo0

Ermal Luçi eri at freebsd.org
Wed Mar 20 15:23:49 UTC 2013


That is intended behavior.
There is an option -m to merge the configs which should not break it.


On Wed, Mar 20, 2013 at 2:49 PM, Andreas Longwitz <longwitz at incore.de>wrote:

> Am 04.03.2013 16:47, schrieb Andreas Longwitz:
>
>  I run FreeBSD 8 Stable with pf enabled and have the line
>>      set skip on lo0
>> in my /etc/pf.conf. Reloading the pf rules with
>>      pfctl -f /etc/pf.conf
>> breaks any active running connections on lo0.
>>
>> Example:
>> -> scp bigfile 127.0.0.1:bigfile.copy
>> bigfile                                      10%   96MB  10.5MB/s
>> 01:15 ETA
>> Write failed: Operation not permitted
>> lost connection
>>
>> In pflog I see
>> 15:33:37.310320    127.0.0.1 -> 127.0.0.1   TCP 164 [block lo0/0]
>>    ssh > 52650 [PSH, ACK] Seq=1 Ack=1 Win=8960 Len=48
>> 15:33:37.310732    127.0.0.1 -> 127.0.0.1    TCP 14452 [block lo0/0]
>>    52650 > ssh [ACK] Seq=1 Ack=1 Win=8960 Len=14336
>> 15:33:37.311153    127.0.0.1 -> 127.0.0.1    TCP 2212 [block lo0/0]
>>    52650 > ssh [FIN, PSH, ACK] Seq=14337 Ack=1 Win=8960 Len=2096
>> 15:33:37.314473    127.0.0.1 -> 127.0.0.1    TCP 116 [block lo0/0]
>>    ssh > 52650 [FIN, ACK] Seq=49 Ack=1 Win=8960 Len=0
>>
>> I can avoid the break on active connections on lo0 using the commands
>>     pfctl -d
>>     pfctl -f /etc/pf.conf
>>     pfctl -e
>> but this may break other things and is not what I want.
>>
>>  From man pf.conf "set skip on .."
>> Packets passing in or out on such interfaces are passed as if pf was
>> disabled, i.e. pf does not process them in any way.
>>
>> I think this should be true for reloading the rules too.
>>
>>
>>  This problem is caused by the way pfctl -f works: In a first step the
> kernel is requested to clear all interface flags, therefore the kernel does
> not respect an old skip lo0 rule anymore. In a second step the new file
> pf.conf - with skip lo0 included - is loaded in the kernel. So there is a
> short time window between step 1 and step 2 without any active skip rule in
> the kernel. A running socket on lo0 will break immediately. This behavior
> of pfctl is well known, see kern/166336.
>
> To get rid of the problem I use the following patch for pfctl. The patch
> executes the first step only if a new option c (=clearifflag) is given.
> Therefore a simple pfctl -f /etc/pf.conf does not break running connections
> on lo0 anymore.
>
> --- pfctl_parser.h.orig 2013-01-14 15:17:48.000000000 +0100
> +++ pfctl_parser.h      2013-03-19 18:22:39.000000000 +0100
> @@ -51,6 +51,7 @@
>  #define PF_OPT_NUMERIC         0x1000
>  #define PF_OPT_MERGE           0x2000
>  #define PF_OPT_RECURSE         0x4000
> +#define PF_OPT_CLRIFFLAG       0x10000
>
>  #define PF_TH_ALL              0xFF
>
> --- pfctl.c.orig        2013-01-14 15:17:48.000000000 +0100
> +++ pfctl.c             2013-03-19 18:40:02.000000000 +0100
> @@ -235,7 +235,7 @@
>  {
>      extern char *__progname;
>
> -    fprintf(stderr, "usage: %s [-AdeghmNnOPqRrvz] ", __progname);
> +    fprintf(stderr, "usage: %s [-AcdeghmNnOPqRrvz] ", __progname);
>      fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
>      fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] ");
>      fprintf(stderr, "[-k host | network ]\n");
> @@ -301,7 +301,8 @@
>  {
>         struct pfioc_iface      pi;
>
> -       if ((opts & PF_OPT_NOACTION) == 0) {
> +       if (((opts & PF_OPT_NOACTION) == 0) &&
> +           ((opts & PF_OPT_CLRIFFLAG) != 0)) {
>                 bzero(&pi, sizeof(pi));
>                 pi.pfiio_flags = PFI_IFLAG_SKIP;
>
> @@ -1980,11 +1981,14 @@
>                 usage();
>
>         while ((ch = getopt(argc, argv,
> -           "a:AdD:eqf:F:ghi:k:K:mnNOo::**Pp:rRs:t:T:vx:z")) != -1) {
> +           "a:AcdD:eqf:F:ghi:k:K:mnNOo::**Pp:rRs:t:T:vx:z")) != -1) {
>                 switch (ch) {
>                 case 'a':
>                         anchoropt = optarg;
>                         break;
> +               case 'c':
> +                       opts |= PF_OPT_CLRIFFLAG;
> +                       break;
>                 case 'd':
>                         opts |= PF_OPT_DISABLE;
>                         mode = O_RDWR;
>
> A better solution for the skip-problem requires assistence of the kernel.
> With a function pfctl_get_interface_flags() pfctl could show the active
> skip interfaces (not possible now) and realize a one shot solution for
> reloading all rules.
>
>
> Andreas Longwitz
> ______________________________**_________________
> freebsd-pf at freebsd.org mailing list
> http://lists.freebsd.org/**mailman/listinfo/freebsd-pf<http://lists.freebsd.org/mailman/listinfo/freebsd-pf>
> To unsubscribe, send any mail to "freebsd-pf-unsubscribe@**freebsd.org<freebsd-pf-unsubscribe at freebsd.org>
> "
>



-- 
Ermal


More information about the freebsd-pf mailing list