FreeBSD PF Firewall

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:



  1. Macros
  2. Tables
  3. Options
  4. Traffic normalization rules (scrub)
  5. Queues, prioritization and speed control
  6. NAT address translation
  7. 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!



All Articles