Introduction
There are many articles on setting up FreeBSD and PF on the Runet, but they are all scattered and unsystematic. And for any more or less interesting things, such as routing by means of a firewall (Policy Based Routing), you have to read the original documentation, for example, the OpenBSD PF FAQ . However, there are differences in command syntax for FreeBSD and OpenBSD. In this series of articles, we try to systematize and analyze the capabilities of PF from simple to complex. For sure, this introductory article will be similar to all other articles about Packet Filter. Therefore, those who are already familiar with the basic features will not be interested. However, one cannot do without an introduction, and the meat will be in the following articles.
PF - Packet Filter is a firewall originally created by the OpenBSD project. Ported to FreeBSD in 2003. In 2004 it was integrated into the main system. Key features:
- Filtering based on addresses, ports, protocols, interfaces
- NAT - Source NAT, substitution of the sender's address. Destination nat, spoofing the recipient address, port forwarding
- Scrub - normalization of network traffic. Helps with some types of dos attacks based on the formation of specially prepared packets
- SYN-proxy - Protection against SYN-flood attacks
- Balancing connections
- โ pfcync , , CARP, ,
- ( IP-, 2 )
- โ
- โ IP
- โ ,
- (anchors) โ , IPTables Linux
- pfstat
The main difference from the same IPTables is the unusual scheme of work. Batch processing does not end after the first rule match. That is, if you set the first rule to โdeny everythingโ , then the packet will not be discarded, but will be marked as prohibited, it will go further according to the rules, and if no rule allows it, it will be discarded. This is important to understand and use. However, if desired, this behavior can be overridden by the quick parameter in the rule.
Management and helpful commands
To enable PF, it is enough to specify the options in the "/etc/rc.conf" file:
pf_enable="YES" # pf pf_flags="" # pfctl pf_rules="/etc/pf.conf" # pflog_enable="YES" # pflog pflog_flags="" # pflog pflog_logfile="/var/log/pflog" #
Basic firewall control commands:
pfctl - # Enable firewall
pfctl -d # Disable firewall
pfctl -nf # Check syntax of
pfctl file -f # Reread rules from file
pfctl -Rf # Reread filter rules from file
pfctl -Nf # Reread NAT rules from file
pfctl -sa # View all states
pfctl -s # View filtering rules
pfctl -sn # View NAT rules
pfctl -s Anchors -v # View anchor tree
pfctl -ss # View current connections
Configuration file structure and basic settings
The configuration file consists of sections:
- Macros
- Tables
- Options
- Traffic normalization rules (scrub)
- Queues, prioritization and speed control
- NAT address translation
- Packet filtering
Rules generally have the following syntax:
action [direction] [log] [quick] [on interface] [af] [proto protocol] [from src_addr [port src_port]] [to dst_addr [port dst_port]] [flags tcp_flags] [state]
action - what should be done with the packet
direction - in out,
log direction - whether the packet will get into pflog
quick - if the packet falls under this rule, then there will be no further processing. This rule will be the last for the
interface packet - the name of the network interface
af - address family, inet or inet6, IPv4 or IPv6, respectively
protocol - layer 4 protocol, for example: tcp, udp, icmp
scr_addr, dst_addr - source and destination
addresses src_port, dst_port -
tcp_flags ports - tcp flags
state - options for saving state. For example, keep state would mean that the connection is kept in the state table and reply packets can go through. Default behavior.
Take the simplest web server in a vacuum. It is necessary to open incoming connections on tcp ports 22, 80, 443 (ssh, http, https). You also need to open outgoing connections on tcp ports 22, 80, 443 (ssh, http, https) and udp 53, 123 (dns and ntp). Prohibit everything else.
# ee pf.conf #macros section permit_tcp_ports="22,80,443" permit_udp_ports="53,123" #table section # #options section set block-policy return # , set skip on lo0 # , #scrub section scrub in all # #Queueing section # #nat section # , #filtering section block all # , , . pass in proto tcp to port { $permit_tcp_ports } # pass out proto tcp to port { $permit_tcp_ports } # tcp pass out proto udp to port { $permit_udp_ports } # udp pass out inet proto icmp # icmp
Then we enter the syntax check command:
pfctl -nf pf.conf
If there are no error messages, enter the command to apply the rules:
pfctl -f pf.conf
To check, let's see the filtering rules:
# pfctl -sr scrub in all fragment reassemble block return all pass out proto tcp from any to any port = ssh flags S/SA keep state pass out proto tcp from any to any port = http flags S/SA keep state pass out proto tcp from any to any port = https flags S/SA keep state pass out proto udp from any to any port = domain keep state pass out proto udp from any to any port = ntp keep state pass out inet proto icmp all keep state pass in proto tcp from any to any port = ssh flags S/SA keep state pass in proto tcp from any to any port = http flags S/SA keep state pass in proto tcp from any to any port = https flags S/SA keep state
As you can see, the macros are expanded into separate rules for each port, the order is changed automatically. Otherwise, everything is as it should be.
Outcome
We figured out what Packet Filter is, learned its main features. Figured out the structure of the PF configuration and its main sections. We created the simplest configuration, which, however, is quite functional, including macros, packet normalization and filtering of incoming and outgoing packets. In the next article, we'll take a closer look at filtering rules, state management, and flags.
Our solution, Internet Control Server, is a security gateway built on top of FreeBSD. This system was chosen because of its stability, speed of the network stack, built-in ZFS support in the kernel, and lack of license issues. Also, working with FreeBSD is enjoyable, albeit not straightforward. But we will be happy to share this experience with you!