So, after cleaning up the interface abstraction code in pf with Ryan 
before the Hackathon, I worked on interface groups integration to pf.

An interface group, is, well, a group of interfaces (surprised, 
anyone?). Interfaces can join and leave interface groups any time, and 
can be member in an arbitary number of groups. The join and leave is 
done via ifconfig:
  ifconfig sk1 group dmz
makes sk1 join the group dmz, and
  ifconfig sk1 -group dmz
removes sk1 from that group again. A group is removed when it does not 
have any members any more and pf does not refer to it.
So far, so good.
Now, pf can use interface groups instead of interfaces basically 
everywhere now. Sounds simple, but is quite powerful.
For example, you can (ab-)use interface groups as a kind of aliasing. 
Just a group with one member, and refer to that. For example, hang your 
dmz of an interface group called "dmz" - if you do this in a consistent
manner, your ruleset is entirely independent from the underlying 
hardware, you make interfaces join the groups in their respective 
hostname.if files which are machine dependent anyway.
now, if you add a second dmz interface for whatever reasons with the 
same policy, you don't even have to modify (usually not even reload) your 
ruleset - just make the 2nd dmz interface join the group :) that of 
course makes much more sense for your "external" interface, where you 
might get a second internet connection, or customer-facing interfaces 
which have the same policies.
pf can refer to interfaces and interface groups which do not exist 
(yet) - once the interface / the group shows up, it will be atached to 
the construct pf uses and (without ruleset reloads!) things Just Work.
Moreover, you can use the brace notation for a dynamic interface name 
to ip address translation, as in,
        pass in on tun0 proto tcp to (tun0) port ssh keep state
and the like. Internally, pf uses a table named after the 
interface inside the _pf anchor, and updates the table whenever there 
are address changes on that interface.
That works for interface groups too, now - including correct handling 
of interfaces joining and leaving the group in question, of course.
so, if you put all your customer-facing interfaces (vlans or physical, 
or any combination... as long as it is interfaces :) ) in a group 
"customers", (customers) correctly expands to all ip addresses on your 
customer-facing interfaces - and (customer:network) to all networks on 
them. And suddenly nice things like
        block in on egress from (customer:network)
work.

For clonable interfaces (almost all virtual ones are, tun, ppp, lo, 
vlan, etc), the clones are all member of an interface class group, for 
example, all loopback interfaces are part of the "lo" interface group, 
all vlan interfaces are part of the "vlan" group, etc. this is 
especially useful in cases where interfaces get created by a daemon on 
a "next free" basis, like tun with userland ppp.

now, we had a sick idea for a while, and since we finally had all the 
parts together now I could implement it - there is an "egress" 
interface group now which follows the default routes.
This interface group contains all interfaces which IPv4 and IPv6 
default routes point to - usually, that is one. It even understands 
multipath routes already, despite them not being useful yet.
The group is updated (actually, rebuilt) every time there is 
changes/additions/deletions of an IPv4 or IPv6 default route.
So, imagine that on your notebook, where you are sometimes on wireless 
and sometimes on wired network connections - just write your pf.conf so 
that it refers to the egress group instead of wi0 and em0, and it will 
Just Work :)

Reply via email to