HomeCurrent ProjectsInterestsResumeE-mail

<< Back to Soekris net4501 FreeBSD Router Project Page

How to Reorder the FreeBSD 4.x
ipf and ipfw Packet Filters
  By Michael R. Brumm

The FreeBSD 4.x kernel has two IP packet filters: ipf and ipfw. Each of these filters have their strengths. Personally, I find it best to use ipf for filtering and translation and use ipfw for traffic shaping. Unfortunately, the order in which packets flow through ipf and ipfw is directionally asymmetrical.

This flowchart shows FreeBSD's rather confusing default packet flow:


incoming packets flow through the packet filters in this order:
ipnat -> ipf -> ipfw

outgoing packets flow through the packet filters in this order:
ipf -> ipnat -> ipfw

This is not only strange and confusing, but it also reduces functionality. For example, if I want to do bandwidth limiting on outgoing packets from clients behind my router's NAT, I cannot distinguish between packets sent from each client based on their IP address in ipfw because ipnat has already translated the NAT client address.

A more sensible order for the packet filtering would be to make ipfw handle the outgoing packets first (before ipf and ipnat). If this is done, the flowchart showing FreeBSD's packet flow is considerably easier to follow:


incoming packets would then flow through the packet filters in this order:
ipnat -> ipf -> ipfw

outgoing packets would then flow through the packet filters in this order:
ipfw -> ipf -> ipnat

To achieve this, I modified the FreeBSD 4.x kernel to recognize two additional sysctl parameters: net.inet.ip.ipfw_in_first and net.inet.ip.ipfw_out_first. The kernel modifications to add the functionality for these sysctl variables were done in ip_input.c and ip_output.c in sys/netinet. I've provided the Kernel Patch Files and Modified Source Code for download.

These new kernel parameters to specify whether ipfw examines the packet before or after ipf (and ipnat). So, to get the packet flow shown in the second diagram, I add the following lines to /etc/sysctl.conf:


    net.inet.ip.ipfw_in_first=0
    net.inet.ip.ipfw_out_first=1


Now, I can use the same source and destination IP addresses in both ipf and ipfw.

<< Back to Soekris net4501 FreeBSD Router Project Page

 

All Material Copyright © Michael R. Brumm