From owner-freebsd-pf@FreeBSD.ORG Wed Mar 20 13:55:02 2013 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 0FF93AA6 for ; Wed, 20 Mar 2013 13:55:02 +0000 (UTC) (envelope-from longwitz@incore.de) Received: from dss.incore.de (dss.incore.de [195.145.1.138]) by mx1.freebsd.org (Postfix) with ESMTP id 96D9C9A3 for ; Wed, 20 Mar 2013 13:55:01 +0000 (UTC) Received: from secmail.incore (inetdns.dmz [10.1.0.3]) by dss.incore.de (Postfix) with ESMTP id DC25A5D92C for ; Wed, 20 Mar 2013 14:49:36 +0100 (CET) Received: from lolap.longwitz (188-181-6-199-dynamic.dk.customer.tdc.net [188.181.6.199]) by secmail.incore (Postfix) with ESMTPS id A352C5C1B for ; Wed, 20 Mar 2013 14:49:36 +0100 (CET) Message-ID: <5149BE75.3040308@incore.de> Date: Wed, 20 Mar 2013 14:49:41 +0100 From: Andreas Longwitz User-Agent: Mozilla/5.0 (X11; FreeBSD i386; rv:15.0) Gecko/20120917 Thunderbird/15.0.1 MIME-Version: 1.0 To: freebsd-pf@freebsd.org Subject: Re: [pach] Reloading pf rules breaks connections on lo0 References: <5134C218.6060701@incore.de> In-Reply-To: <5134C218.6060701@incore.de> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Mar 2013 13:55:02 -0000 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