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@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-pf
To unsubscribe, send any mail to "freebsd-pf-unsubscr...@freebsd.org"

Reply via email to