FreeBSD Kernel PatchesAaron's IPFW Patches
Photo: Pine Valley Mountain Across Sand Mountain's RocksIPv4You are not logged in. Click here to log in.
Aaron's IPFW Patches for FreeBSD
FreeBSD's IPFW IP filtering software is a requirement for any FreeBSD box I administer. However, the statefule IP filtering in IPFW has one significant limitation that I dislike. A dynamic rule that is created to statefully pass UDP or TCP traffic eventually will expire based on the state of the traffic stream and the settings of several global sysctl variables. Unfortunately, as an administrator who likes to follow the "everything that is not explicitly permitted is denied" ethic, I must increase the global timeouts in order to pass traffic statefully for just a very few protocols (SSH and telnet among them) that have sessions that tend to idle longer than the default timeout settings.
The solution to this dilemma is the ability to override the default sysctl expiration lifetime settings on a per-rule basis. And thus the patches below were born.
Thanks to Crist J. Clark for suggesting how to make the patches more efficient. The patches include his suggested improvements since 6 July 2001.
IPFW Patch Sets:
PLEASE NOTE: The patches are listed below in reverse chronological order, newest at the top. Please remember that there are two sets of patches, the lifetime set (adds per-rule lifetime expiration control), and the state set (adds stricter expiration of dynamic TCP rules when unusual states/conditions occur). For FreeBSD 4.x, there are separate versions of these two patch sets for ipfw and ipfw2.
Patch Change History:
I originally wrote the ipfw lifetime patches for FreeBSD 4.0-STABLE, submitting the first version to the firstname.lastname@example.org mailing list on 5 June 2000, subsequently filing FreeBSD PR #22065 offering the patches to add this feature to FreeBSD (and later PR #28713).
02 NOV 2005: No real updates to the patches were needed from 5.3 to 6.0. Nevertheless, I updated them to reduce the delta in future changes. Only offsets changed.
04 NOV 2004: Originally I was going to abandon these patches, switching from ipfw to pf on my systems when I upgraded for 5.3-RELEASE. I have too many systems using ipfw to make that realistic, so I'll keep maintaining these patches it looks like. Also, ipfw, while missing some of the very nice state tracking, modulation, and scrubbing abilities of pf, and missing in-kernel NAT, it has a well-defined flow so you know exactly what happens to each packet and when. With ipfw I can exactly control when network address translation happens with precision, as well as control when stateful dynamic rule matching is performed. Useful stuff!
20 JAN 2004: I finally got around to updating my home system from 5.1 to 5.2. The patches for 5.1-RELEASE still applied cleanly to 5.2-RELEASE and everything appears to be working fine.
30 OCT 2003: The patches for 4.8 appear to apply cleanly to 4.9-RELEASE, no changes required. I'm now doing a buildworld/installworld to make sure everything works well.
14 AUG 2003: Just a quick update for 4.8-STABLE so that the ipfw2 patch will again apply cleanly. And I thought I was done with patching the 4.x line... *chuckle*
09 JUN 2003: Now that 5.1-RELEASE is here and quite stable (at least on the system I installed 5.0-RC1 on back in December and then tracked 5.x, updating periodically), I probably won't be updating the patches for the 4.x line anymore. Actually I haven't had to modify the patches for 4.x since 4.6-STABLE in Sept. of 2002. Hopefully no modifications will be necessary until 5.x becomes the new -STABLE line.
21 DEC 2002: Finally I took the plunge and installed 5.0-RC1 to begin familiarizing myself with 5.0. So far it's been quite stable for me, in spite of a few minor rough edges (to be expected in a release candiatate on the -CURRENT tree). Hopefully the 21 Dec. 2002 patches for the 5.0 tree will apply cleanly to RC1. They do apply cleanly to -CURRENT as of 21 Dec. 2002.
09 September 2002: Updated patches for -STABLE for both IPFW and IPFW2 systems and switched to a table format to list patch versions available.
01 August 2002: Added new patch sets for Luigi Rizzo's IPFW2 system for 4.6-STABLE.
17 June 2002: I've added another ipfw patch set that fixes what I personally consider a deficiency in the ipfw stateful handing machine where certain packets should be blocked. Situations where this actually occur are VERY RARE, so most people probably don't need the new ipfwstate patches at all, or may even disagree with what they do. I personally think that it is a cleaner, clearer way of handling invalid TCP states within ipfw with a log message. This new patch set is useful when playing with a complex ipfw and network translation set-up where a misconfiguration can cause the middle (second) packet of a 3-way TCP handshake to "miss" or bypass a rule. In such cases, a log entry appears in the logs, prompting the administrator to fix the ruleset flow. Likewise, if for some reason an outside hacker sends a TCP SYN packet followed by a TCP ACK packet, pretending that he/she received the middle TCP SYN+ACK, with this patch, the subsequent ACK packet is dropped with a log message and the dynamic rule is expired. That just makes sense to me. If I'm using dynamic rules, my ipfw machine MUST be "in the middle" of all TCP sessions utilizing those rules, so if a packet is missiong from the three-way handshake, I want the dynamic rules associated with that session to expire as soon as the invalid state is detected, and I want the offending packet dropped.
The lifetime patch set modifies two kernel files (so you have to rebuild your kernel) as well as the ipfw command itself (and the ipfw man page too). Just copy the patch file to your /usr/src directory, use it to patch the files, copy a header file, then rebuild your kernel and the ipfw command:
Once installed, you can now override the global dynamic rule lifetime expiration times controlled by various sysctl variables on a rule-by rule basis (or you can NOT override it and use the default ipfw behavior). For example, this lets me allow HTTP connections to port 80 the usual way using the default behavior while overriding the timeout on SSH (port 22) TCP connections so that my SSH sessions don't timeout after 5 minutes of inactivity. Here's an example based on firewall rules for a single workstation:
See the ipfw man page (after you apply the patches and install it) for more documentation, in particular the stateful rule section where the lifetime extension that the patches add is covered.
I have been running these patches for well over a year now on several firewalls and also on several moderate-to-high traffic hosts on the Internet with no trouble at all.
Since Luigi Rizzo add TCP keepalive packet generation to ipfw2 certain applications no longer require these patches. If, however, you do not want your firewall to generate TCP keepalive traffic--and there are cases where this may be desired--these patches remain useful. Even with ipfw2, non-TCP IP protocols still benefit from finer grained per-rule lifetime control.
To turn off TCP keepalive packet generation under ipfw2 do this:
Or set the same variable to zero in your
Or you can do it on the fly using the
I personally prefer that my firewall NOT generate TCP keepalive traffic. One reason is that with TCP keepalive traffic being automatically generated by the firewall, if a TCP session terminates abnormally (due to a reboot or perhaps a network problem) and the near side has this feature enabled, and the other side has a very picky silent-discard rule-set, that other side, when it is back online, will continue to see TCP keepalive traffic periodically even though there are no established TCP sessions until the dynamic rule finally expires on the near side. I suppose this could be alleviated by not silently dropping "bogus" established TCP traffic on the remote side firewall and instead sending out a RST to terminate the left-over dynamic rule on the near side, but why bother. I just hate having extraneous and unnecessary traffic for any reason on my network.
If you do rely on ipfw2's TCP keepalive feature, you have to make sure that your rule sets allow that traffic to be sent. It's easy to accidentally block or deny it without realizing.
Let Me Know
IF YOU USE THESE PATCHES please drop me a note on my Contact Me web page and let me know how you use the patches.