Unix Technical Forum

Skipping interfaces in pf [was: pf filtering on loopback?]

This is a discussion on Skipping interfaces in pf [was: pf filtering on loopback?] within the mailing.openbsd.tech forums, part of the OpenBSD category; --> --nextPart4755159.Kb29qF1htq Content-Type: multipart/mixed; boundary="Boundary-01=_fGzvBav3YvX5FWs" Content-Transfer-Encoding: 7bit Content-Disposition: inline --Boundary-01=_fGzvBav3YvX5FWs Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Hi, in an ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 07:29 AM
Max Laier
 
Posts: n/a
Default Skipping interfaces in pf [was: pf filtering on loopback?]

--nextPart4755159.Kb29qF1htq
Content-Type: multipart/mixed;
boundary="Boundary-01=_fGzvBav3YvX5FWs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

--Boundary-01=_fGzvBav3YvX5FWs
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi,

in an earlier thread Daniel suggested that it might be a good idea to skip =
pf=20
processing on lo0:
http://www.monkey.org/openbsd/archiv.../msg00061.html

Another thread on freebsd-net:
http://lists.freebsd.org/pipermail/f...er/005906.html
is discussing the possible overhead with filtering interfaces that do not=
=20
transport any IP-level data or in setups with huge LAN pipes that you don't=
=20
want to filter on.

As a solution I'd like to propose a new option "skip on <interface>" that=
=20
disables filtering on the listed interface(s). I realize this as a flag in=
=20
the already existing pf internal interface list. See attachment. The cost i=
s=20
a simple compare and the gain should be obvious.

To give some more motivation think of a setup where you have some GigE=20
interfaces facing your LAN/DMZ and you don't want to filter them (which is=
=20
very common). You will write a ruleset like:

block all
pass on { $if0, $if1, ... $ifN }
#ruleset goes here

The optimizer will also put these rules in front of the processing as there=
=20
are a lot of matches. Still every packet on $ifN will have to go through N=
=20
rules (skip-steps don't help) and every packet that really is filtered has=
=20
that O(N) overhead in front as well.

It might be worthwhile to extend this to be able to skip only certain=20
processing. e.g.:

set skip all on <interface>
Will skip all (surprise)
set skip from scrub on <interface>
Will evaluate scrub rules and end processing afterwards.
set skip from nat on <interface>
Will evaluate scrub and nat rules and stop afterwards.

I am open to changes regarding syntax and implementation, but think that th=
e=20
idea itself is good.

Comments?

--=20
/"\ Best regards, | mlaier@freebsd.org
\ / Max Laier | ICQ #67774661
X http://pf4freebsd.love2party.net/ | mlaier@EFnet
/ \ ASCII Ribbon Campaign | Against HTML Mail and News

--Boundary-01=_fGzvBav3YvX5FWs
Content-Type: text/x-diff;
charset="us-ascii";
name="skip.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="skip.diff"

Index: sbin/pfctl/parse.y
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.469
diff -u -r1.469 parse.y
--- sbin/pfctl/parse.y 10 Dec 2004 22:13:26 -0000 1.469
+++ sbin/pfctl/parse.y 14 Dec 2004 17:37:42 -0000
@@ -281,6 +281,7 @@
struct node_queue_bw bwspec, struct node_queue_opt *);
int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
struct node_queue_bw, struct node_queue_opt *);
+int expand_skip_interface(struct node_if *);
=20
int check_rulestate(int);
int kw_cmp(const void *, const void *);
@@ -398,7 +399,7 @@
%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
-%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG HOSTID
+%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
%token ANTISPOOF FOR
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
@@ -570,6 +571,12 @@
}
free($3);
}
+ | SET SKIP interface {
+ if (expand_skip_interface($3) !=3D 0) {
+ yyerror("error setting skip interface(s)");
+ YYERROR;
+ }
+ }
;
=20
string : string STRING {
@@ -4446,6 +4453,35 @@
yyerror("rule expands to no valid combination");
}
=20
+int
+expand_skip_interface(struct node_if *interfaces)
+{
+ int errs =3D 0;
+
+ if ((!interfaces) ||=20
+ ((!interfaces->next) && (!interfaces->not) &&
+ (strcmp(interfaces->ifname, "none") =3D=3D 0))) {
+ errs =3D pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
+ return (errs);
+ }
+
+ LOOP_THROUGH(struct node_if, interface, interfaces,
+ if (interface->not) {
+ yyerror("skip on ! <interface> is not supported");
+ errs++;
+ } else
+ errs +=3D pfctl_set_interface_flags(pf,
+ interface->ifname, PFI_IFLAG_SKIP, 1);
+ );
+
+ FREE_LIST(struct node_if, interfaces);
+
+ if (errs)
+ return (1);
+ else
+ return (0);
+}
+
#undef FREE_LIST
#undef LOOP_THROUGH
=20
@@ -4565,6 +4601,7 @@
{ "rule", RULE},
{ "scrub", SCRUB},
{ "set", SET},
+ { "skip", SKIP},
{ "source-hash", SOURCEHASH},
{ "source-track", SOURCETRACK},
{ "state", STATE},
Index: sbin/pfctl/pfctl.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sbin/pfctl/pfctl.c,v
retrieving revision 1.223
diff -u -r1.223 pfctl.c
--- sbin/pfctl/pfctl.c 21 Sep 2004 16:59:11 -0000 1.223
+++ sbin/pfctl/pfctl.c 14 Dec 2004 17:37:42 -0000
@@ -1270,6 +1270,39 @@
}
=20
int
+pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int h=
ow)
+{
+ struct pfioc_iface pi;
+
+ if ((loadopt & PFCTL_FLAG_OPTION) =3D=3D 0)
+ return (0);
+
+ bzero(&pi, sizeof(pi));
+
+ pi.pfiio_flags =3D flags;
+
+ if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=3D
+ sizeof(pi.pfiio_name))
+ errx(1, "pfctl_set_interface_flags: strlcpy");
+
+ if ((pf->opts & PF_OPT_NOACTION) =3D=3D 0) {
+ if (how =3D=3D 0) {
+ if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
+ err(1, "DIOCCLRIFFLAG");
+ } else {
+ if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
+ err(1, "DIOCSETIFFLAG");
+ }
+ }
+
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("%s %s:0x%x flags\n", how?"set":"clear", pi.pfiio_name,
+ pi.pfiio_flags);
+
+ return (0);
+}
+
+int
pfctl_debug(int dev, u_int32_t level, int opts)
{
if (ioctl(dev, DIOCSETDEBUG, &level))
Index: sbin/pfctl/pfctl_parser.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sbin/pfctl/pfctl_parser.h,v
retrieving revision 1.77
diff -u -r1.77 pfctl_parser.h
--- sbin/pfctl/pfctl_parser.h 16 Jul 2004 23:44:25 -0000 1.77
+++ sbin/pfctl/pfctl_parser.h 14 Dec 2004 17:37:42 -0000
@@ -187,6 +187,7 @@
int pfctl_set_logif(struct pfctl *, char *);
int pfctl_set_hostid(struct pfctl *, u_int32_t);
int pfctl_set_debug(struct pfctl *, char *);
+int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
=20
int parse_rules(FILE *, struct pfctl *);
int parse_flags(char *);
Index: sbin/pfctl/pfctl_table.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sbin/pfctl/pfctl_table.c,v
retrieving revision 1.61
diff -u -r1.61 pfctl_table.c
--- sbin/pfctl/pfctl_table.c 12 Jun 2004 22:22:44 -0000 1.61
+++ sbin/pfctl/pfctl_table.c 14 Dec 2004 17:37:42 -0000
@@ -577,7 +577,8 @@
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
- oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 1);
+ oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
+ oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
printf("\n");
=20
if (!(opts & PF_OPT_VERBOSE2))
Index: share/man/man4/pf.4
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/share/man/man4/pf.4,v
retrieving revision 1.53
diff -u -r1.53 pf.4
--- share/man/man4/pf.4 10 Dec 2004 03:29:02 -0000 1.53
+++ share/man/man4/pf.4 14 Dec 2004 17:48:38 -0000
@@ -1013,6 +1013,19 @@
.Va pfiio_nzero
will be set by the kernel to the number of interfaces and drivers
that have been cleared.
+.It Dv DIOCSETIFFLAG Fa "struct pfioc_iface *io"
+Set the user setable flags (described below) of the pf internal interface
+description.
+The filtering process is the same as for
+.Dv DIOCIGETIFACES .
+.Bd -literal
+#define PFI_IFLAG_SKIP 0x0100 /* skip progressing */
+#define PFI_IFLAG_SETABLE_MASK 0x0100 /* setable via DIOC{SET,CLR}IFFLAG */
+.Ed
+.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
+works as
+.DV DIOCSETIFFLAG
+above but clears the flags.
.El
.Sh FILES
.Bl -tag -width /dev/pf -compact
Index: share/man/man5/pf.conf.5
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/share/man/man5/pf.conf.5,v
retrieving revision 1.314
diff -u -r1.314 pf.conf.5
--- share/man/man5/pf.conf.5 12 Dec 2004 17:41:55 -0000 1.314
+++ share/man/man5/pf.conf.5 14 Dec 2004 17:33:04 -0000
@@ -483,6 +483,16 @@
.Pp
.Dl set fingerprints \&"/etc/pf.os.devel\&"
.Pp
+.It Ar set skip on <interface>
+List interfaces that should not be included in the ruleset progressing.
+This can be helpful for lo0 and interfaces that only see encapsulated
+traffic (e.g. pppoe).
+If skipping is enabled on a given interface can be determined with
+.Xr pfctl 8 .
+To disable skipping on all interfaces (default) use:
+.Pp
+.Dl set skip on none
+.Pp
.It Ar set debug
Set the debug
.Ar level
Index: sys/net/pf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sys/net/pf.c,v
retrieving revision 1.474
diff -u -r1.474 pf.c
--- sys/net/pf.c 14 Dec 2004 03:49:06 -0000 1.474
+++ sys/net/pf.c 14 Dec 2004 16:27:10 -0000
@@ -5627,6 +5627,8 @@
kif =3D pfi_index2kif[ifp->if_index];
if (kif =3D=3D NULL)
return (PF_DROP);
+ else if (kif->pfik_flags & PFI_IFLAG_SKIP) /* later? */
+ return (PF_PASS);
=20
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) =3D=3D 0)
@@ -5934,6 +5936,8 @@
kif =3D pfi_index2kif[ifp->if_index];
if (kif =3D=3D NULL)
return (PF_DROP);
+ else if (kif->pfik_flags & PFI_IFLAG_SKIP) /* later? */
+ return (PF_PASS);
=20
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) =3D=3D 0)
Index: sys/net/pf_if.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sys/net/pf_if.c,v
retrieving revision 1.22
diff -u -r1.22 pf_if.c
--- sys/net/pf_if.c 13 Dec 2004 23:51:22 -0000 1.22
+++ sys/net/pf_if.c 14 Dec 2004 16:25:31 -0000
@@ -689,6 +689,44 @@
}
=20
int
+pfi_set_flags(const char *name, int flags)
+{
+ struct pfi_kif *p;
+
+ if (flags & ~PFI_IFLAG_SETABLE_MASK)
+ return (EINVAL);
+
+ s =3D splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p, PFI_FLAG_GROUP|PFI_FLAG_INSTANCE))
+ continue;
+ p->pfik_flags |=3D flags;
+ }
+ splx(s);
+
+ return (0);
+}
+
+int
+pfi_clear_flags(const char *name, int flags)
+{
+ struct pfi_kif *p;
+
+ if (flags & ~PFI_IFLAG_SETABLE_MASK)
+ return (EINVAL);
+
+ s =3D splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p, PFI_FLAG_GROUP|PFI_FLAG_INSTANCE))
+ continue;
+ p->pfik_flags &=3D ~flags;
+ }
+ splx(s);
+
+ return (0);
+}
+
+int
pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
{
struct pfi_kif *p;
Index: sys/net/pf_ioctl.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.136
diff -u -r1.136 pf_ioctl.c
--- sys/net/pf_ioctl.c 10 Dec 2004 22:13:26 -0000 1.136
+++ sys/net/pf_ioctl.c 14 Dec 2004 16:26:17 -0000
@@ -1028,6 +1028,8 @@
case DIOCCLRSRCNODES:
case DIOCIGETIFACES:
case DIOCICLRISTATS:
+ case DIOCSETIFFLAG:
+ case DIOCCLRIFFLAG:
break;
case DIOCRCLRTABLES:
case DIOCRADDTABLES:
@@ -2767,6 +2769,20 @@
break;
}
=20
+ case DIOCSETIFFLAG: {
+ struct pfioc_iface *io =3D (struct pfioc_iface *)addr;
+
+ error =3D pfi_set_flags(io->pfiio_name, io->pfiio_flags);
+ break;
+ }
+
+ case DIOCCLRIFFLAG: {
+ struct pfioc_iface *io =3D (struct pfioc_iface *)addr;
+
+ error =3D pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
+ break;
+ }
+
default:
error =3D ENODEV;
break;
Index: sys/net/pfvar.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D
RCS file: /usr/store/mlaier/ocvs/src/sys/net/pfvar.h,v
retrieving revision 1.209
diff -u -r1.209 pfvar.h
--- sys/net/pfvar.h 10 Dec 2004 22:13:26 -0000 1.209
+++ sys/net/pfvar.h 14 Dec 2004 16:24:18 -0000
@@ -869,6 +869,8 @@
#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */
#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */
#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */
+#define PFI_IFLAG_SKIP 0x0100 /* skip progressing */
+#define PFI_IFLAG_SETABLE_MASK 0x0100 /* setable via DIOC{SET,CLR}IFFLAG */
=20
struct pf_pdesc {
u_int64_t tot_len; /* Make Mickey money */
@@ -1326,6 +1328,8 @@
#define DIOCSETHOSTID _IOWR('D', 86, u_int32_t)
#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface)
#define DIOCICLRISTATS _IOWR('D', 88, struct pfioc_iface)
+#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
+#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
=20
#ifdef _KERNEL
RB_HEAD(pf_src_tree, pf_src_node);
@@ -1488,6 +1492,8 @@
void pfi_fill_oldstatus(struct pf_status *);
int pfi_clr_istats(const char *, int *, int);
int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
+int pfi_set_flags(const char *, int);
+int pfi_clear_flags(const char *, int);
int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
sa_family_t);
=20

--Boundary-01=_fGzvBav3YvX5FWs--

--nextPart4755159.Kb29qF1htq
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (FreeBSD)

iD8DBQBBvzGkXyyEoT62BG0RAh1KAJsHwbfEk+5gbFPf2eh97M LB2RiqPACeLlwd
d0GjZCyM84rmMAri2w8lrJ8=
=V0L9
-----END PGP SIGNATURE-----

--nextPart4755159.Kb29qF1htq--

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 09:05 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com