The information about PF in FreeBSD handbook is at chapter 33. Freebsd Firewalls

Why setup a firewall? Security issues are detected in a few seconds.

My server is getting scanned all the time

The manual has more details about pfctl and the configuration file pf.conf:

man pfctl
man pf.conf

Starting PF

sysrc pf_enable=yes
sysrc pflog_enable=yes
service pf start
service pflog start

sysrc configures the system to start pf at boot and service starts pf immediately.

pfctl -e                          Enable PF.
pfctl -F all -f /etc/pf.conf      Flush all NAT, filter, state, and table rules and reload /etc/pf.conf.
pfctl -vnf /etc/pf.conf           Check /etc/pf.conf for errors, but do not load ruleset.

pfctl -vnf doesn't check the table sizes, default table size is 65535 entries.

Creating rules

In this configuration, pf blocks the nets listed in the blocked file, allows connections to the ssh server only from the networks listed in the allow file and drops ping. There are too many botnets connecting to the ssh server, so I allow only my machines to connect to it. I don't use ping so I drop it. My machines get 100 pings per second from everywhere on the internet, the botnets are using ping to guess to the geographical location of the machines.

vi /etc/pf.conf

table <allow> persist file "/etc/allow"
table <blocked> persist file "/etc/blocked"

set skip on lo0
scrub in

pass out keep state

block quick from <blocked>
block quick inet proto tcp from ! <allow> to any port ssh
block quick inet proto icmp all icmp-type 8 code 0
  • set skip on lo0 doesn't apply any rule to the local network interface
  • scrub in reassembles the ip fragments
  • pass out keep state allows outgoing connections initiated by the host, the iptables equivalent in linux is iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
  • block quick inet proto icmp all icmp-type 8 code 0 drops pings, iptables equivalent is iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
  • block quick from <blocked> blocks packets from the networks listed on blocked, the iptables equivalent is iptables -A INPUT -m set --match-set blocked src -j DROP
  • table <allow> persist file "/etc/allow" creates a table called allow with the networks listed in /etc/allow. allow looks like this:
1.2.3.4/8
45.46.47.48/16

The default table size is 65535, when a table exceeds the maximum size this error happens:

pfctl -f /etc/pf.conf
/etc/pf.conf:2: cannot define table x: too many elements.
Consider increasing net.pf.request_maxcount.
pfctl: Syntax error in config file: pf rules not loaded

To increase the maximum table size, run:

sysctl net.pf.request_maxcount=131071

With ipset in linux, the tables (sets) are created like this:

ipset create blocked hash:net hashsize 262144 maxelem 262144

New networks can be added to tables at any time with:

pfctl -t allow -T add 192.168.1.0/16

With ipset, networks are added with:

ipset add blocked 1.0.0.0/8

The command pfctl -si shows some statistics and counters.

Hashtags: #freebsd #firewall