pefs and l2filter moved to github

December 9, 2009 by · Leave a Comment 

I’ve just moved pefs and l2filter development to github. Hope it helps people follow development.

pefs repository ( can be used to to compile and run pefs without applying any patches.

pefs changelog:
* support running on msdosfs
* enable dircache only on file systems that are known to support it
* add man page
* add pefs getkey command
* intial implementation of pefs PAM module

l2filter repository ( contains only patches. There is fresh patch against 8-STABLE with some minor improvements comparing to 7-STABLE version. 9-CURRENT patch is a bit outdated at the moment, as I’m waiting for Luigi Rizzo to finish ipfw refactoring work first.

Besides I’ve moved my blog to
Please update your bookmarks. I do not intend to update blog freebsdish any more.

Updated l2filter patches

May 15, 2009 by · 2 Comments 

Patches include fix for ether-only address handling in pf and should apply cleanly to recent sources (7-STABLE and 8-CURRENT)



layer2 dummynet

March 24, 2009 by · 7 Comments 

Haven’t posted about progress with lyear2 filtering for a while. One notable improvement is addition of ethernet address masks to dummynet.

Just configure a pipe. New masks available: src-ether and dst-ether (and a shortcut for specifying both of them: ether)
# ipfw pipe 1 config bw 1Mb mask ether

And use it:
# ipfw add 1100 pipe 1 src-ether 00:11:11:11:11:11 dst-ether 00:22:22:22:22:22 out via bridge0 layer2
# ipfw add 1200 pipe 1 dst-ether 00:11:11:11:11:11 src-ether 00:22:22:22:22:22 out via bridge0 layer2

# ipfw pipe show
00001: 1.000 Mbit/s 0 ms 50 sl. 2 queues (64 buckets) droptail
mask: ff:ff:ff:ff:ff:ff -> ff:ff:ff:ff:ff:ff tag: 0x0000
BKT _Source Ether Addr_ _Dest. Ether Addr__ Tag Tot_pkt/bytes Pkt/Byte Drp
40 00:11:11:11:11:11 00:22:22:22:22:22 0 2 196 0 0 0
43 00:22:22:22:22:22 00:11:11:11:11:11 0 2 196 0 0 0

Besides, masking packet by tag is also there:
# ipfw add 200 pipe 1 ip from any to any tagged 1-1000 via bridge0 layer2

As several tags per packet supported, it is necessary to specify desired tag range, tag, or any tag:
# ipfw add 200 pipe 1 ip from any to any tagged any via bridge0 layer2

Patches for current and 7-stable available:
l2filter-stable-2009-03-24 (updated link)

ipfw: layer2 lookup tables

November 23, 2008 by · 2 Comments 

I had an opportunity to spend some extra time improving layer2 filtering.
I’ve extended lookup tables in ipfw to support several layer2 addresses for a single layer3 address/mask. It means that it’s possible to assign mac addresses to network (in case ip’s are dynamically distributed by dhcp or whatever). Besides, wildcard ip address ‘any’ is supported, and entries with wildcard ip can be used for layer2 filtering.

For example:

ipfw table 1 add ether 00:11:11:11:11:11
ipfw table 1 add ether 00:22:22:22:22:22
ipfw table 1 add ether 00:33:33:33:33:33

# equivalent to: ipfw table 2 add any ether ...
ipfw table 2 add ether 00:11:11:11:11:11
ipfw table 2 add ether 00:22:22:22:22:22
ipfw table 2 add ether 00:33:33:33:33:33
ipfw table 2 add ether ff:ff:ff:ff:ff:ff

ipfw add 1000 allow ip from 'table(2)' to 'table(2)' layer2

# layer3
ipfw add 2000 allow ip from 'table(1)' to 'table(1)'

Layer2 filtering in pf

July 30, 2008 by · 4 Comments 

Instead of trying to describe all the changes regarding layer2 filtering in pf I’d better provide some examples.

Ethernet address can be specified for host or interface name:
pass in on bridge0 from ether 00:11:11:11:11:11 to ether 00:22:22:22:22:22
pass in on bridge0 from ($int_if:network) ether 00:11:11:11:11:11 to any

Ethernet addresses are supported in table entries:
table <test> persist { ether 00:11:11:11:11:11, ether 00:22:22:22:22:22}
pass on bridge0 from <test> to <test> keep state (ether)

Ethernet stateful filtering is handled specially. Per rule flag is added to conditionally enable ethernet stateful filtering (disabled by default):
pass log on bridge0 from <test> to <test> keep state (ether)

With keep state (ether) enabled pf uses real source and destination ethernet addresses from the first packet to create the state and uses these addresses afterwards to match the state.

filtering on bridge

June 29, 2008 by · Leave a Comment 

There used to be a flaw in using ipfw on bridge interface. It’s impossible to distinguish incoming packets on member interface from incoming packets on bridge itself. For example consider two rules:
add 1 allow ip from any to any in recv bridge
add 2 allow ip from any to any in recv member

First rule will never match. The logic is ok here (if you are aware of ipfw’s handling of interface options). But what do you expect if you disable filtering on member interfaces and perform filtering on bridge only. You expect rule 1 to match all incoming packets on bridge. It gets extremely annoying when using stateful filtering.

First time I came across this issue several years ago. But didn’t figure out how to fix it. At that time I’ve decided to switch to pf.

Actually ipfw is the only firewall that allow rules like
allow ip from any to any out recv if1 xmit if2
Such tricks are possible because ipfw gets input interface from mbuf of a packet. pf for example relies on pfil to provide interface.

I’ve added a hack into if_bridge to work around it. It contradicts traditional ipfw behaviour a little but seems to be much more useful. I think patches are useful enough and can be commited into FreeBSD:

incompatibility and some new features

June 22, 2008 by · 1 Comment 

Yep. I’ve made some changes that break backward compatibility :)
But I’ve tried not to break anything intentionally but to do a cleanup work.

First of all most of sysctl’s responsible for layer2 filtering were replaced by per interface flags. and are replaced by l2filter interface flag.
So sysctl became ifconfig if1 l2tag. was renamed to

Introduced l2tag interface flag. It’s purpose is to add mbuf tag containing source and destination layer2 addresses to every packet passing through interface. Note that l2tag filtering against layer2 addresses is performed in layer3.

When invoked from layer2 ipfw no longer touches layer2 headers. So they following rule won’t work anymore:
ifpw allow ip from to any src-ether 00:11:11:11:11:11 layer2

ipfw mac option was replaced by to two options: src-ether and dst-ether. ipfw still accepts mac option but translates it into src-ether and dst-ether.

Lookup tables support layer2 addresses now:
ipfw table 1 add ether 00:11:11:11:11:11
ipfw allow ip from table(1) to any

ipfw mac-type was renamed to ether-type. Support for mac-type preserved.

Stateful filtering remains somewhat special. The problem here is that l2tag is added to a packet only in input path (when invoked from ether_demux). Such decision was intentional, mainly because it’s impossible to get tag added in output path without serious layer violations or entire pfil framework and packet handling redesign. That’s why a packet that has no l2tag attached, will pass against layer2 dynamic rule.

Dynamic rules (state created by the rule) do not check both source and destination layer2 address, but just the addresses specified by the rule created it. For example
ifpw allow ip from to any src-ether 00:11:11:11:11:11 keep-state
will create dynamic rule that checks only source ethernet address of a packet, but not destination.