As of July 2003 the OpenBSD firewall software application named PF was ported to FBSD. It has become the third firewall software application delivered as an integrated part of the base system install. PF is a complete, fully featured firewall that has optional support for ALTQ (Alternate Queuing). ALTQ provides Quality of Service (QoS) bandwidth shaping that allows guaranteeing bandwidth to different services based on filtering rules. The OpenBSD project does such an outstanding job of maintaining the PF user's guide that it will not be made part of this Installer Guide as that would just be duplicated effort.More Info can be found at http://pf4freebsd.love2party.net/index.html
The OpenBSD PF user's guide is found at http://www.openbsd.org/faq/pf/index.html
The FBSD handbook has been updated to contain some information on PF http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/firewalls-pf.html
The PF program runs in the kernel and consists of the firewall and integrated NAT facilities. PF also has user-land front-end interfaces for controlling the firewall filter and NAT rules, and the logging facility. Program pfctl is used to load the firewall rules. The syntax of the filter rules are very similar to those of IPfilter (IPF).
PF's 3 weakness's are it's logging is primitive in that the logged data is written in binary, logging does not utilize the syslogd facility, and the rule number in the logged data listed by the tcpdump command does not correspond to the /etc/pf.conf text file. Debugging the filter rules is harder due this this.
PF was originally written using a rules processing logic of ‘the last matching rule wins’ and used only stateless types of rules. Over time PF has been enhanced to include a ‘quick’ option and a stateful ‘keep state’ option which drastically modernized the rules processing logic. PF’s official documentation covers the legacy rule coding parameters and the legacy rule file processing logic, the modernized functions are completely explained in detail highlighting their benefits in producing a far superior secure firewall.
The instructions contained in this guide are based on using rules that contain the ‘quick' option and the stateful ‘keep state’ option. This is the basic framework for coding an inclusive firewall rule set.
An inclusive firewall only allows services matching the rules through. This way you can control what services can originate behind the firewall destined for the public internet and also control the services which can originate from the public internet accessing your private network. Everything else is blocked and logged by default design. Inclusive firewall rule sets are much more secure than exclusive firewall rule sets and are the only rule set type covered herein.
Since all firewalls are based on interrogating the values of selected packet control fields, the creator of the firewall rules must have an understanding of how TCP/IP works, what the different values in the packet control fields are and how these values are used in a normal session conversation. For a good explanation go to http://www.ipprimer.com/overview.cfm
Installers Note:If you are following the 'incremental install method' recommended in this Installers guide, them you only need to concern your self with the building of a rules file at this time. After you have the Lan hardware configured and tested then you need to return to this section to enable NAT and configure it’s rules.
PF is included in the basic FreeBSD install as a separate run time loadable module. The system will dynamically load the PF kernel loadable module when the rc.conf statement pf_enable="YES" is used. The loadable module was created with pflog logging enabled, no ALTQ support, and defaults to pass all packets.
Using the PF run time loadable module is recommended.
It is not a mandatory requirement that you enable PF by compiling the following options into the FreeBSD kernel. It is only presented here as background information. Compiling PF into the kernel causes the runtime loadable module to never be used.
Sample kernel config PF option statements are in the /usr/src/sys/conf/NOTES kernel source and are reproduced here:
device pf enables support for the “Packet Filter” firewall.
device pflog enables the optional pflog pseudo network device which can be used to log traffic to a bpf descriptor. The pflogd daemon can be used to store the logging information to disk.
device pfsync enables the optional pfsync pseudo network device that is used to monitor “state changes”. As this is not part of the loadable module one has to build a custom kernel to use it.
ALTQ is only available by compiling the options into the FreeBSD Kernel. ALTQ is not supported by all of the available network card drivers. Please see the altq manual page for a list of drivers that are supported in your release of FreeBSD.
The following options will enable ALTQ and add additional functionality.
options ALTQ_CBQ # Class Bases Queuing (CBQ)
options ALTQ_RED # Random Early Detection (RED)
options ALTQ_RIO # RED In/Out
options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
options ALTQ_PRIQ # Priority Queuing (PRIQ)
options ALTQ_NOPCC # Required for SMP build
options ALTQ enables the ALTQ framework.
options ALTQ_CBQ enables Class Based Queuing (CBQ). CBQ allows you to divide a connection's bandwidth into different classes or queues to prioritize traffic based on filter rules.
options ALTQ_RED enables Random Early Detection (RED). RED is used to avoid network congestion. RED does this by measuring the length of the queue and comparing it to the minimum and maximum thresholds for the queue. If the queue is over the maximum all new packets will be dropped. True to its name, RED drops packets from different connections randomly.
options ALTQ_RIO enables Random Early Detection In and Out.
options ALTQ_HFSC enables the Hierarchical Fair Service Curve Packet
Scheduler. For more information about HFSC see:
options ALTQ_PRIQ enables Priority Queuing (PRIQ). PRIQ will always pass traffic that is in a higher queue first.
options ALTQ_NOPCC enables SMP support for ALTQ. This option is required on SMP systems.
These settings will take effect only after you have built and installed a kernel with them set.
To build a custom kernel see the Kernel Customizing section.
You need the following statements in /etc/rc.conf to activate PF at boot time:
pf_enable="YES" # Enable PF (load module if required)
pf_rules="/etc/pf.conf # rules definition file for pf
pflog_enable="YES" # start Logging function
pflog_logfile="/var/log/pflog" # where pflogd should store the log file
If you have a LAN behind this firewall and have to forward packets for the computers in the LAN or want to do NAT, you have to enable the following option as well:
gateway_enable="YES" # Enable as LAN gateway
After boot, PF operation can be managed using the pfctl command.
Some example commands are:
pfctl -f /etc/pf.conf # loads the pf.conf file
pfctl -nf /etc/pf.conf # parse the file, but don't load it
pfctl -Nf /etc/pf.conf # Load only the NAT rules from the file
pfctl -Rf /etc/pf.conf # Load only the filter rules from the file
# Show the current NAT rules
pfctl -sr # Show the current filter rules
pfctl -ss # Show the current state table
pfctl -si # Show filter stats and counters
pfctl -sa # Show EVERYTHING it can show
pfctl -e # Enable PF
pfctl -d # Disable PF
Note that this just enables or disables PF, it doesn't actually load a rule set. The rule set must be loaded separately, either before or after PF is enabled. For a complete list of commands, please see the pfctl man page.
The pfctl command is used to load your rules file. The pfctl command expects the rules file to be a standard text file. Normally you create a text file containing your custom rules and use this command to replace in mass the currently running firewall internal rules. It's advisable to first flush the current internal rules and state table entry's before loading the rule set to a running environment.
pfctl -F all
pfctl -f /etc/pf.conf
This gives the user the ability to make changes to their custom rules file and run the above pfctl command, thus updating the running firewall with a fresh copy of all the rules without having to reboot the system. This method is very convenient for testing new rules as the procedure can be executed as many times as needed.
A rule set is a group of PF rules coded to pass or block packets based on the values contained in the packet. The bi-directional exchange of packets between hosts comprises a session conversation. The firewall rule set processes the packet two times, once on its arrival from the public Internet host and again as it leaves for its return trip back to the public Internet host. Each TCP/IP service (IE: telnet, www, mail, etc;) is predefined by its protocol, source and destination IP address, or the source and destination port number. This is the basic selection criteria used to create rules which will pass or block services.
PF was originally written using a rules processing logic of ‘the last matching rule wins’ and used only stateless types of rules. Over time IPF has been enhanced to include a ‘quick’ option and a stateful ‘keep state’ option which drastically modernized the rules processing logic.
The instructions contained in this section are based on using rules that contain the ‘quick' option and the stateful ‘keep state’ option. This is the basic framework for coding an inclusive firewall rule set.
An inclusive firewall only allows services matching the rules through. This way you can control what services can originate behind the firewall destined for the public Internet and also control the services which can originate from the public Internet accessing your private network. Everything else is blocked and logged by default design. Inclusive firewall rule sets are much more secure than exclusive firewall rule sets and are the only rule set type covered herein.
Installers Note:Warning, when working with the firewall rules, always, always do it from the root console of the system running the firewall or you can end up locking yourself out.
The logging function is compiled into the PF run time loadable module.
To activate, you need this line added to /etc/rc.conf
The logged data defaults to writing in /var/log/pflog
This default can be changed by adding this statement to /etc/rc.conf
If you change the default log file name you also have to change it in newsyslog.conf so it will get rotated. PF does not use the syslogd facility.
The logged data is written in binary and can not be displayed directly. You need to use tcpdump command to convert the binary records to ASCII text.
tcpdump -n -e -ttt -r /var/log/pflog > /var/log/pflog.txt
Because pflogd logs in tcpdump binary format, the full range of tcpdump
features can be used when reviewing the logs. For example, to only see packets
that match a certain port:
tcpdump -n -e -ttt -r /var/log/pflog port 80
This can be further refined by limiting the display of packets to a certain host and port combination:
tcpdump -n -e -ttt -r /var/log/pflog port 80 and host 192.168.1.3
A real-time display of logged packets is achieved by using the pflog0
tcpdump -n -e -ttt -i pflog0
As packets are logged they will show up on your monitor screen. This is most helpful when testing a new rules file or to monitor your firewall when your system is under attack.
This FreeBSD Installer Guide is an public domain HOW-TO. This content may be reproduced, in any form or by any means, and used by all without permission in writing from the author.