NPF
Speaker: Zoltan Arnold Nagy
Zoltan was a GSoC student. His goal was to add ip6 support to NPF (this was committed in early November). Mindaugas Rasiukevicius, the announced co-speaker who had to be excused, is the initiator of the NPF project.
1. What is a firewall?
A firewall can be defined as a function taking as an argument a packet, and returning a boolean "drop", "keep" result.
Several implementations techniques are:
- an expression tree;
- an acyclic control flow graph;
- some spaghetti code.
The first technique is too slow at the execution. Existing firewalls tend to use the third option. Mindaugas Rasiukevicius estimated that the second option would enable a fast and efficient, parallelisable firewall implementation.
2. Firewalls in BSD land
The *BSD systems have several firewalls to choose from:
- ipfilter, the traditional firewall that was abandoned because of a license change1;
- ipfw (FreeBSD-specific);
- pf (from the OpenBSD world; though both FreeBSD and NetBSD lag behind the OpenBSD version, with 4.5 and 4.2 respectively);
- and now, NPF (from NetBSD).
The first draft of NPF was written in about a year, committed in August 2010 to the CVS tree. It will be the default firewall in NetBSD 6.0.
After Zoltan's ip6 support, the next big step for NPF is to remove the use of the BKL.
3. Motivations
Zoltan insisted that NPF was not started because NetBSD felt like having its own firewall, but rather because it was hard to clean existing implementations. The objectives when designing NPF were the following:
- multi-processor safety;
- performance, fast look-up of rules (introduce as little latency as possible to the streams going through the firewall);
- N-code processor;
- stateful filtering of connections;
- an extensible and modular architecture;
- simple, portable code.
The N-code processor is a bytecode engine used to determine the fate
of a packet. It is similar in spirit to the bpf filters that power
tcpdump(8)
to determine whether a packet matches the user selection.
However, this is a new implementation.
4. Usage
The userland tool is npfctl(8)
. It communicates with the kernel
component through a device node /dev/npf
with ioctls.
The rules are first compiled into an N-code representation, then
loaded. The syntax is quite close to that of pf. A significant update
is the notion of interface groups, that allows to specify
per-interface rules. This is in contrast with the pf approach: in pf,
there is an on $interface
keyword, optionally attached to any rule,
and every rule needs to be checked on each new packet.
5. Discussion
The talk attracted a lot of people, so much that the organisation had to move to the main conference room because the planned room was too small. Maybe this was in part because of the quite trollish tone of the abstract:
IPFilter was not designed with a modern SMP world in mind, and while it has been preferred packet filter for a while – its current focus and future directions are uncertain. OpenBSD's PF lacks general design principles. Potential improvements and maintenance of its code base are problematic.
Maybe in part because firewalling in the BSD world would seem a solved problem —after all, the Internet was developed on *BSD systems— so the need of a new firewall is rather intriguing.
Next to me in the audience was a group of pf developers. They were, as
could be expected, those who asked the most questions. They seemed to
like what they saw. In particular, they started talking about stealing
some ideas from NPF, for instance storing netmasks as the length (fits
into a char
) instead of the full bitmask (32 or 128 bits), thus
trading some CPU time for memory.
Another interesting question was about the safety of the firewall. Since the engine of NPF compiles rules into code that is evaluated at run-time, did we just invent a VM whose halting condition on an arbitrary input packet is not decidable? That would be rather disappointing for a firewall implementation whose objectives include performance… Zoltan answered by saying the execution flow always provably goes forwards. This does not give guarantees about maximum execution times, though.
Zoltan mentionned during his talk the possibility of plugging external modules. After all, modularity and extensibility were desired properties of NPF. One of the main use he envisionned of external modules was filtering above the traditional TCP / UDP layer (in other words, layer 7 filtering aka DPI). For instance, only SIP sessions having certain properties would be allowed through. However, there currently does not exist such module. In addition, a concern of the audience was the potential risks with allowing external modules in the firewall engine (impact on performance and on correctness).
Footnotes:
Much ado (not quite about nothing) on the OpenBSD lists when the license change happened is recorded in the archives. LWN also have some coverage, and there were discussions on the NetBSD lists. Surprisingly, I did not find archives of similar discussions on the FreeBSD mailling lists. To this day, both FreeBSD and NetBSD include ipfilter in the base system. DragonflyBSD and OpenBSD removed ipfilter.