Pf
The Berkeley Packet Filter (pf) is a firewall utility.
pf(4) is run as a service, while pfctl(8) is a userland interface.
Installation
All BSD distributions have pf(8) installed.
Note that the FreeBSD implementation has diverged from the upstream project.
Configuration
For the most basic of usecases, this is perfect.
block in all pass out all keep state
To check the configuration of pf(4), run...
pfctl -nf /usr/local/etc/pf.conf
Basic Server Setup
A server needs to be addressable by the external network. In order to minimize repetition, macros should be used to store the TCP and UDP ports that need to be opened.
tcp_services = "{ 22 53 80 443 }" udp_services = "{ 53 }" icmp_types = "echoreq" # Basic inbound TCP rule pass in inet proto tcp $tcp_services flags S/SA keep state # Basic inbound UDP rule pass in inet proto udp $udp_services keep state # Basic ICMP ping rule pass inet proto icmp all icmp-type $icmp_types keep state # Basic outbound connections rule pass out proto tcp all modulate state flags S/SA pass out proto { udp, icmp } all keep state
If you have dedicated interfaces for internal and external networks, it becomes much simpler to create rules.
ext_if="xl0" int_if="xl1" localnet=$int_if:network # hardened firewall block drop in quick on $ext_if from $localnet to any block drop out quick on $ext_if from any to $localnet # hardened ICMP rules pass inet proto icmp from $localnet to any keep state pass inet proto icmp from any to $ext_if keep state
Blocking Brute Force Attacks
Clients that attempt a high number of connections are often brute force attackers. pf(4) can easily add these addresses to a blacklisted table.
localnet = "{ 192.168.100.0/24 }" tcp_services = "{ 22 }" table <bruteforce> persist block quick from <bruteforce> pass inet proto tcp from any to $localnet port $tcp_services \ flags S/SA keep state \ (max-src-conn 100, max-src-conn-rate 15/5, \ overload <bruteforce> flush global)
The <bruteforce> table can be cleared based on an expiry time (in seconds) using pfctl(8).
pfctl -t bruteforce -T expire 86400
This can be automated with a cron job.