Lock down your FreeBSD VPS with the pf firewall
pf is one of the best reasons to run FreeBSD. It's a powerful, genuinely readable packet filter built into the base system — the same engine that has anchored BSD firewalls and routers for two decades. On LYLIX you get two layers: the cloud firewall at the hypervisor (managed from the portal, in front of the VM) and pf inside the guest. Use both for defense in depth.
A hardened starting ruleset
Create /etc/pf.conf. This blocks everything inbound by default and opens only what you serve:
ext_if = "vtnet0" # your NIC (virtio on KVM)
tcp_services = "{ 22 80 443 }" # SSH + web; edit to taste
set skip on lo
set block-policy drop
scrub in all
# Brute-force table: hosts that trip the rate limit below land here
table <bruteforce> persist
block quick from <bruteforce>
block in all
pass out all keep state
# SSH with rate limiting: 5 new connections / 30s per source -> blocked
pass in on $ext_if proto tcp to port 22 \
keep state (max-src-conn-rate 5/30, overload <bruteforce> flush global)
pass in on $ext_if proto tcp to port $tcp_services keep state
pass in inet proto icmp icmp-type echoreq
pass in inet6 proto icmp6 icmp6-type { echoreq neighbrsol neighbradv }
Enable and manage it
sysrc pf_enable=YES
service pf start
pfctl -f /etc/pf.conf # reload after edits
pfctl -s rules # show active rules
pfctl -t bruteforce -T show # who's in the brute-force table
pfctl -d # disable pf (emergency)
Test before you trust it
Keep a portal browser console session open while you test a new ruleset. If a rule locks out SSH, the console still gets you in to run pfctl -d and fix /etc/pf.conf. See the console guide.
NAT and port redirects
Running services in jails or building a WireGuard gateway? pf does the NAT. For example, to forward public port 8080 to a jail on an internal address and NAT its outbound traffic:
rdr pass on $ext_if proto tcp to port 8080 -> 10.10.0.2 port 80
nat on $ext_if from 10.10.0.0/24 to any -> ($ext_if)
Brute-force mitigation without fail2ban
The portal's fail2ban panel is Linux-only, and you don't need it here. The overload table above is pf's native equivalent for SSH and any TCP service. For deeper integration, FreeBSD's blacklistd hooks directly into sshd and feeds offenders into a pf table automatically. The hypervisor cloud firewall is the belt-and-suspenders that applies regardless of what's running inside the guest.