The upcoming release of OpenBSD 3.3 on May 1'st will include, among many other improvements, a notably enhanced version of PF, OpenBSD's stateful packet filter. Some of the more significant enhancements to PF include: 'queues', allowing for per-rule bandwidth control [story]; 'pool options', allowing one to utilize multiple uplinks and to intelligently redirect traffic to multiple servers; 'anchors', which allow one to divide packet filtering rule lists into logical pieces; 'tables', efficiently allowing for very large lists; and other parser improvements that make an already friendly syntax more human readable.
PF replaced its predecessor, IPF, with the release of OpenBSD 3.0 in December of 2001. Since that time, this impressive and relatively new packet filter has grown a faithful following (myself included), and continues to evolve rapidly with each new OpenBSD release. Perhaps the greatest compliment, developers have begun to port PF to other operating systems. Back in January, Joel Wilsson announced his effort to port PF to NetBSD. And more recently, Pyun YongHyeon announced his port for FreeBSD.
I approached Pyun to learn more about his recent porting efforts. In the following article he explains why he began working on this port, and what FreeBSD users can expect from the project. Additionally, I spoke with PF creator Daniel Hartmeier [interview], PF developer Henning Brauer, and OpenBSD creator Theo de Raadt [interview]. They all reflect on these recent porting efforts, as well as the exciting new features found in OpenBSD's PF.
Pyun YongHyeon announced his port of PF to FreeBSD in the end of March, however the effort began a month before that. Pyun explains, "Since the release of OpenBSD 3.0, pf was [the] primary firewall on my company's office. At that time pf was basically the same as ipfilter. ipfilter has more advantages on state tracking against ipfw. pf has supported all alike features. I loved pf's features and saw its possibility of latent powers.
"Because I'm FreeBSD user I really have wanted to run it on my FreeBSD machine. If FreeBSD can run it, pf can make full advantage of advanced features of FreeBSD such as SMP, KSE, etc. I had looked forward to running pf on FreeBSD. Because any one who ever used pf would know its advantages over ipfw, it was matter of time.
"I had seen many requests for pf on FreeBSD but core members of FreeBSD had not merged pf. It seemed that they did not need another packet filter any more due to FreeBSD supporting both ipfw and ipfilter. I got tired of waiting for pf, have changed my mind to do it myself at about the end of Feb. 2003."
The homepage for Pyun's FreeBSD port of PF includes an earlier version based upon the current OpenBSD 3.2, as well as another more recent port based on the upcoming OpenBSD 3.3. I asked Pyun how complete and functional he felt his port was, to which he replied, " How complete/functional is a very difficult question. pf is far from complete. The port is in ALPHA stage. Many features of pf have not been tested yet. Although basic features of pf such as filtering, state tracking, 1:N NAT works fine on my box. All support code from pf was included except ALTQ. pf has many features and it takes time to experiment with all of it. It needs more feedback from users for [this project to be a] success."
That begs the question, what's left to be done? Pyun explained that his current port disables ALTQ until ALTQ is added to the FreeBSD 5 tree. Pyun went on to say, "In addition to this, there are many things left to do. Here are some of them.
"I have made my level best to port it as it is in OpenBSD. But there are substantial differences between FreeBSD and OpenBSD. To port it as exact as possible, FreeBSD kernel code and data structures should be changed. It would be rejected by core members because its aspect on pf."
When I asked Pyun if he had received any help from OpenBSD developers when porting PF, he explained, "No. I have not even tried it. But reading the FAQ and mailing lists on pf was great help to me. It was my own desire to run pf on FreeBSD by myself due to no one ever [having] tried it. Also I thought this is not an issue for OpenBSD developers. (They already have perfect pf.) Actually, I have not mailed to any OpenBSD developers. Only after my first port came out, I have written to OpenBSD Journal."
We went on to discuss the feedback that Pyun has received since announcing his port. He said, "Unfortunately, I have not gotten a mail from FreeBSD kernel developers yet. They may not even know about pf for FreeBSD.
"I got many replies from both FreeBSD and OpenBSD users. Most of them were from users who used pf on OpenBSD. Some of them offered a dedicated home page. Many of them said words of encouragement and thanks. Especially, Max Laier has set up a dedicated home page and CVS server. He also has become co-developer for pf on FreeBSD. Without his enthusiastic help and patience on my broken english, it would not be possible to continue porting pf. Now pf for FreeBSD has an official home page."
Comparing PF To Other Packet Filters
Personally being a fan of PF, I was quite curious to know how it compares to FreeBSD's other packet filters. Pyun noted that while this may be possible eventually, the port is not yet ready for this type of comparison. He explains, "As I said earlier, my port is far from complete. In addition to this, the two have taken different approaches to the same problem. It seems it is a matter of user's taste and policy. ipfw is a good packet filter. It has it own features and advantages over the other packet filter. So direct comparison to ipfw is not possible though I am under a bias toward pf in all aspects."
"When pf for FreeBSD matures we may be able to compare pf with ipfw and ipfilter on the same machine, OS and rules. At that time we can say which one is better than this objectively."
Looking forward, Pyun expressed his hopes for this port, "To me, armed with FreeBSD's advanced feature, just to use pf on FreeBSD as if I can on OpenBSD. To other FreeBSD users, I want to let them know there is another excellent packet filter. To FreeBSD kernel developers, I would like to express demands for pf. In the long run, I look forward to merging pf into the base system."
OpenBSD Developer Reactions
I approached PF creator Daniel Hartmeier to learn if he was aware of Pyun's efforts. Daniel replied, "I just read about the port on deadly.org last week, and I'm in the process of installing a FreeBSD machine so I can test the port. There seems to be some (smaller) problem with rdr and checksums, and I hope I can help track that down and submit a patch to Pyun. I'll also have to see what parts had to be replaced (like mbuf tags) and how they're done in FreeBSD."
Regarding the existence of other ports, Daniel commented, "There was some announcement of a NetBSD port, but I never saw a tarball with sources, so I haven't tested that yet. If someone is actively maintaining or using it, I'd be interested to hear."
Interested in his opinion on these recent porting efforts, I asked Daniel for his reaction. He replied, "It's great to see that people from other BSDs are getting interested in pf, especially when someone with kernel programming knowledge is willing to invest the time to get things working. The more time I see others invest, the more obliged I feel to contribute to the port, of course. It would be great to get the basics working, so people can give it a try and compare the functionality and performance (which I'm quite curious about, too)."
PF developer Henning Brauer also commented on the recent porting efforts, "I appreciate those. Of course, as a pf developer, I'm convinced pf is superior to the other available packet filters, and the fact that ports are done is a sign of appreciation for our work."
The Difficulties Of Porting
Of course, though OpenBSD, NetBSD and FreeBSD share a common ancestry, they have long since diverged paths. As PF lives in the kernel, it's not as simple as recompiling it to get it working on another operating system. I asked Daniel what some of the harder issues might be when porting PF, to which he explained, "There are some parts which rely on things that are done differently on other BSDs (like mbuf tags or pool memory), but there's a counterpart or alternate implementation/api for each of those, I'm sure. One of the new things in 3.3 is the integration of pf with altq, which might be a larger piece of work, if altq isn't part of the target platform yet."
Regarding this recent merge, Theo de Raadt pointed out that it was not a minor effort. He explained, "To make pf and altq get married, altq has been significantly modified. The altq that kjc wrote has been heavily modified on the ioctl-end to be able to merge into the semantics we needed in for queue. If some other system has basic boring regular altq, they have got quite an effort ahead of them."
Henning also reflected on the difficulties of porting PF, adding, "There was more than one NetBSD port. NetBSD is easier as NetBSD is more similar to OpenBSD than FreeBSD, namely, NetBSD has pool(9) and since a few weeks mbuf tags. FreeBSD doesn't have pool(9), so the port to FreeBSD included changing that to zone(9), and they do not have mbuf tags the way we have but use another scheme."
Using The PF Port In FreeBSD
By the time I'd prepared this article, Daniel had already given Pyun's port a preliminary try. He described this experience, saying, "I now have a FreeBSD box running 5.0-RELEASE and the pf port as a kernel module. It will require some serious testing, but the basic functions like filtering statefully and translations (NAT, redirections) work fine so far. It's likely that there are some bugs to be found and fixed, especially in the less commonly used features, but the port appears to be stable and hasn't crashed once for me.
"Max Laier set up a page with the latests tarballs (which include some important bugfixes) and installation instructions on http://pf4freebsd.love2party.net/, I'd recommend fetching the source from there and giving him and Pyun feedback."
What's New With PF In OpenBSD 3.3
One of the biggest changes to PF in OpenBSD 3.3 is the recent merging of ALTQ. Daniel demonstrates the power of this merge in his informative paper titled "Prioritizing empty TCP ACKs with pf and ALTQ", offering instructions on how to configure the packet filter to prevent an upload from affecting download throughput, with impressive results.
Theo was responsible for the initial design of merging ALTQ with PF. The end result, referred to as queueing, offers per-rule bandwidth control. Henning, who lead the actual implementation efforts, describes how the merge resulted in a much different and more powerful queueing engine than the earlier KAME version. He explains, "well, the whole classifier is dead and replaced by pf. That means that this whole part is replaced, and thus, the whole interface is changed. Look, the only kernel<->userland interface is basically feeding the classifier, that sorts packets into different queues, feeding it the rules. Before the merge altq had its own classifier, working on a per interface basis, and being... "hard" to use. Now pf does this. And we work cross-interface, that really rocks: you classify a packet on the incoming interface (an mbuf tag is used and the queuing happens on the outgoing interface...
"Another thing, and that is really new, is the stateful nature you have with using keep state rules and queuing on those. In the state table entries we have a pointer back to the rule that created the state, and from that rule we get the queue ID(s) to classify the packets matching the state. This means you can now prioritize outgoing _connections_ instead of packets. This is really new, connection based queuing instead of packet based."
Theo further describes, "A major part of this design is that you can do queue settings on not just pass rules, but also on block rules. For a block rule, the queue setting is used for any rejection packets. This permits management of icmp or rst traffic."
An overview of the new features found in PF with the upcoming release of OpenBSD 3.3 can be found in these slides from Henning's recent presentation at FOSDEM 2003 in Brussels, Belgium. A complete overview of the packet filter including the new features can be found in these slides from Daniel's recent presentation at LinuxForum in Copenhagen, Denmark.
Daniel also offered a summary of the more major new features in PF, "The most important changes in 3.3 are probably:
pass from { s1, s2, ..., sN } to { d1, d2, ..., dM }where N and M are large. This gets expanded to N*M rules by the parser, so every combination of source and destination address is passed. Evaluating a large list of such rules can get slow. Tables are just a list of addresses (or netblocks), like
pass from <src> to <dst>
where 'src' and 'dst' are arbitrary names. You can load huge lists of addresses into each one (using pfctl), and the kernel builds a binary radix tree. The rule doesn't have to be expanded, and evaluation can be done using two simple lookups, which is very fast even with huge lists (tens of thousands of entries).
"We've given some talks during the last couple of weeks presenting those and other changes. If you're interested, you can view most of the slides on http://www.openbsd.org/events.html."
I asked Daniel about rumors I'd heard of support for firewall redundancy being added recently, to which he replied, "We don't have firewall redundancy and failover yet, that's something to tackle for 3.4. But with 3.3, you can already balance load to multiple uplinks or servers, like a redirection rule that forwards incoming HTTP requests to multiple local web servers, distributing the load according to various schemes (round-robin, source hash, etc.). It's also possible to make use of multiple Internet connections (uplinks), spreading outgoing connections across all of them (or based on any criteria the filter can use, like protocols, ports or addresses), and routing replies back through the uplink where an incoming connection arrived on."
OpenBSD 3.3
OpenBSD 3.3 will be available on May 1'st, 2003. It can be freely downloaded from a local FTP mirror, or purchased as a 3-CD set, which includes images for i386, MacPPC, Vax, Sparc, and Sparc64. Versions for Alpha, HP300, HPPA, Mac68k and MVME68k are available by FTP. The project's homepage states, "OpenBSD is developed by volunteers. The project funds development and releases by selling Cd's and T-shirts, as well as receiving donations. Organizations and individuals donate and thus ensure that OpenBSD will continue to exist, and will remain free for everyone to use and reuse as they see fit."
Linux?
How about porting this to Linux? Or are there technical/political reason not to do it? Or is it simply a case of NIH ("Not Invented Here")?
iptables
isn't iptables good enough? How do they compare (pf vs. iptables)?
It's all about the syntax
A common gripe about iptables is the very awkward syntax (especially in comparion with pf's, which is so much more easy to read).
To forward all traffic to port 80 to port 8080 on a machine inside the LAN in pf:
rdr on $ext proto tcp from any to $ext port 80 -> 192.168.40.1 port 8080
The iptables equivalent:
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -j DNAT --to 192.168.0.2:8080
iptables -A FORWARD -p tcp -i eth0 -d 192.168.40.1 --dport 8080 -j ACCEPT
Just compare http://www.openbsd.org/faq/faq6.html#PF with http://www.liniac.upenn.edu/sysadmin/security/iptables.html and you'll see what I mean. :)
It's all about the speed (in theory)
Some poeple consider the syntax with pf is simple to read. But I disagree with it, maybe because I more used to Checkpoint and IPTables.
BTW, the concept of configuring pf is "The last matching rule wins" compare to others "The first matching rule wins".
This has made me uncomfortable with it.
What if I have 1000 rules, is that means pf always compare 1000 times before decide to block or pass?
Any comment is welcome !!
- Jet
jchan@trusecure.com
quick keyword
You only have to add the "quick" keyword in your rule for pf to stop parsing rules when such a rule matches.
PF "quick" modifier
PF rule syntax allows for the inclusion of a "quick" modifier, which ensures that, on a match, that rule is the last evaluated. Just use the modifier on all your rules if you prefer the "first matching rule wins" approach.
Provides for great flexibility.
JC
There are skip-steps that ena
There are skip-steps that enable pf to skip over rules that can't match. So if you group your ruleset (and with 1000 rules you most likely will) by interface, src/dst-ip, etc. pf will only look at the first rule of each block and skip the rest (in case the first didn't match).
Moreover with concepts like tables (e.g.) you won't need as much rules as with other filters. And tables are very quick and comfortable to use.
Max
superflous line
The "FORWARD" line you have is not needed, unless you have it blocked. If so, you need an equivalent statement in pf.
PF vs IPTables
According to the comments in this story, IPTables does not do stateful inspection/filtering, only connection tracking. As to how that would impact your needs, that is something you need to investigate. To me it sounds like a shortcoming in IPTables, one that hopefully will be changed.
If I had the necessary skills and time, porting PF to Linux would be a fun project for me, not too mention a huge learning experience. But alas, neither exists. Why port? Because choice can be good.
Re: PF vs IPTables
The difference between a firewall that does "stateful inspection/filtering" and one that does connection tracking and allows packets to be matched based on connection state is too subtle for me.
Do you care to explain what it is?
Also, it is possible to add your own state to packets in iptables with "marks".
Re: PF vs IPTables
The difference between a "stateful inspection/filtering" firewall and a firewall that does packet matching based on tracked connection state is too subtle for me. I don't see a difference at all.
Could you explain what it is?
And, in case you don't consider connected status to be enough state, iptables also allows your rules to mark packets and does connection tracking at the application protocol layer for some common protocols.
Re: PF vs IPTables
With 'stateful filtering', pf means associating each TCP packet with the connection it is part of, verifying all sequence numbers in each packet with the narrow windows of expected/legitimate values.
The theory for tracking the sequence number windows is laid out in Guido van Rooij's paper 'Real Stateful TCP Packet Filtering in IP Filter' (http://home.iae.nl/users/guido/papers/tcp_filtering.ps.gz).
There's a patch for netfilter that implements this tracking, see
http://www.netfilter.org/documentation/pomlist/pom-extra.html#tcp-window...
But afaik, it's still not part of the default distribution.
Ok, I see
Basically what you are saying is that iptables is missing the sequence number validation. It just looks at sIP+sport+dIP+dport to check for membership in a connection.
comments
Why do my replies to this message not show up?
Basically, I believe you are wrong. I don't see the difference between a stateful filter and what iptables does.
Re: Linux
porting pf to linux is basically impossible due to the heavy technical differences.
Re: Linux
Which are....?
Impossible is nothing.
PF port for GNU/Linux:
- http://abstractvoid.se/pf4lin.html
Do you try it?
I had been trying to install openbsd on a hp servers, i have kernel panics with the scsi card.
But no problems installing centos. If its works it could be very easy to me, centos with pf
everybody happy :D
Forget my by my english :P
How do the BSD packet filters deal with ftp, irc, ...
How do the BSD packet filters deal with protocols that open
extra connections based on data in the packet payload, e.g.
FTP data connections, IRC DCC, TFTP transfers, etc. ?
Linux netfilter/iptables connection tracking has this nice concept
of connection tracking and NAT helpers, which really makes for
a very powerful system.
it's done with userland tool
it's done with userland tools, like ftp-proxy.
Userland
Is there a way for ftp-proxy to communicate information about the connection back to the kernel for matching in the firewall rules?
Userland kernel
Yes.
That's the whole purpose of ftp-proxy.
Can you kill off individual connections?
Is there a way in pf to kill off an individual FTP / HTTP / SMTP session? IE you find that there's a malicious user, or one that's hung up and still connected to a machine behind pf.
Can you easily find out who is connected (ip list) to a box behind pf? Easy to kill off individual sessions? get stats on the session, like connection time and bandwidth used?
RTFM
Read pfctl(8)
#pfctl -k host
Kill all of the state entries originating from the specified host.
pfTop
There's also a package named: pftop-0.3.tgz
checkout: http://www.eee.metu.edu.tr/~canacar/pftop/