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"