Server PF Boilerplate
Date: 20251216
Scope:
PF built into OpenBSD and FreeBSD can give protection to services running on a server. To avoid any performance penalties and where filtering is not required for specific services, this should deviate away from block all/allow to block known/restrict. In this configuration, users must be aware of the services they are running because accidentally exposed services will immediately be available on the wire.
Instructions:
On FreeBSD, enable pf and pflog (see below). PF on OpenBSD is on by default:
service pf enable && service pf start service pflog enable && service pflog start
Set up tables to include your management addresses. There should be no reason for adhoc connectivity to these hosts for management functions. Use tables instead of macros to reduce the rule set and speed up rule evaluation. While tables do use more memory, this is less of an issue these days, but the performance increase is noticeable on large rule sets:
table <mgmt_v6> persist { 2001:db8:dead:1::/64 }
table <mgmt_v4> persist { 198.51.100.0/24 }Not mandatory, but a lot of mirror maintainers have issues with not only AI bots but China Mobile. They will use mirrors or servers with large data sets outside of their network to shore up bandwidth ratios on their international transit providers. This is completely optional and depends on the audience you are trying to attract with the service:
table <china_mobile> persist { 111.0.0.0/10, 223.64.0.0/10, 2409:8000::/20 } # Problematic provider that uses your resources for ingress balanceRestrict IPv6 and IPv4 ICMP types to only what is necessary for the server to connect and provide health status:
icmp6_types="{ unreach, toobig, timex, paramprob, echoreq, echorep, routeradv, routersol, neighbradv, neighbrsol }"
icmp4_types="{ unreach, timex, paramprob, echoreq }"Loopback interfaces typically don't need protection or filtering. Set PF to skip this interface so it doesn't get included by any rule evaluation by accident:
set skip on lo
Block all known management services. Typically, set to drop for these services so they aren't visible and avoids detection in high-speed network scans. To reduce connection load and terminate connections if they don't match an evaluation rule, change rules from drop to return:
block drop in quick from <china_mobile> block drop in log proto tcp to port ssh block drop in log proto udp to port snmp block drop in proto icmp6 block drop in proto icmp
For the above management services, create rules for explicit access to these services:
## ICMP pass inet6 proto icmp6 icmp6-type $icmp6_types pass inet proto icmp all icmp-type $icmp4_types ## SSH pass in log inet6 proto tcp from <mgmt_v6> to port ssh pass in log proto tcp from <mgmt_v4> to port ssh ## SNMP pass in log proto udp from <mgmt_v6> to port snmp
Once rule build is complete, validate the The changes:
pfctl -nf /etc/pf.conf
If there are no syntax errors, perform a load of the rules:
pfctl -f /etc/pf.conf
Build on the above rule set for service or site-specific requirements. Further details on traffic management can be found in the relevant in the OpenBSD and FreeBSD pf.conf man pages.
Complete /etc/pf.conf rule set:
table <mgmt_v6> persist { 2001:db8:dead:1::/64 }
table <mgmt_v4> persist { 198.51.100.0/24 }
table <china_mobile> persist { 111.0.0.0/10, 223.64.0.0/10, 2409:8000::/20 } # Problematic provider that uses your resources for ingress balance
icmp6_types="{ unreach, toobig, timex, paramprob, echoreq, echorep, routeradv, routersol, neighbradv, neighbrsol }"
icmp4_types="{ unreach, timex, paramprob, echoreq }"
set skip on lo
block drop in quick from <china_mobile>
block drop in log proto tcp to port ssh
block drop in log proto udp to port snmp
block drop in proto icmp6
block drop in proto icmp
## ICMP
pass inet6 proto icmp6 icmp6-type $icmp6_types
pass inet proto icmp all icmp-type $icmp4_types
## SSH
pass in log inet6 proto tcp from <mgmt_v6> to port ssh
pass in log proto tcp from <mgmt_v4> to port ssh
## SNMP
pass in log proto udp from <mgmt_v6> to port snmpEnd of Document
