Skip to content

Instantly share code, notes, and snippets.

@TGion
Last active August 10, 2023 04:47
Show Gist options
  • Save TGion/3012105dd4a97fd24d29cd0c61661370 to your computer and use it in GitHub Desktop.
Save TGion/3012105dd4a97fd24d29cd0c61661370 to your computer and use it in GitHub Desktop.
Different BSD packet filter (pf) rule snippets - IPv4 only
ext_if = "vtnet0" # Our external interface.
vpn_if = "wg0" # Wireguard interface
gsd_if = "wg-gsd" # Wireguard GSD interface
# TCP ports allowed for external / public interface.
TCP_EXT_OK = "{ domain-s, http, https, docsrv }"
UDP_EXT_OK = "{ domain-s, wireguard }"
# Stateful TCP options.
TCP_STATE = "flags S/FSRA keep state"
# TCP ports allowed outbound
# TCP_OUT_OK = "{ domain-s, http, https, smtps, imaps, ssh }"
# UDP ports allowed outbound
# UDP_OUT_OK = "{ domain-s, ntp }"
# IPv6 link local prefix.
#PFX_LNKLOC = "FE80::/10"
# IPv6 Solicited Node Multicast Prefix.
#MC_SOLNOD = "FF02::1:FF00:0/104"
# IPv6 All Nodes Link Local Multicast Address.
#MC_NODLNK = "FF02::1"
# IPv6 All Routers Link Local Multicast Address.
#MC_RTRLNK = "FF02::2"
### TABLES ###
# Non-routable adresses - should be ignored by me
table <martians> const { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16 \
172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24 \
192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24 \
240.0.0.0/4 255.255.255.255/32 }
# Abusers are added to this table, which is flushed after 24h
# IPs in this table have low bandwith assigned
table <flooders> persist counters
# Imported abusers table
# IPs in this table are blocked
# pf-badhost - https://geoghegan.ca/pub/pf-badhost/latest/install/freebsd.txt
table <pfbadhost> persist file "/etc/pf.badhost"
# table <pfgoodhost> persist file "/etc/pf.goodhost" # pf-goodhost - Hosts should always be allowed - careful
table <home> persist { fritzbox.gion.io } # DDNS Clients with priority access (e.g. FritzBox)
table <sslabs> const { 64.41.200.0/24 64.39.109.20 104.130.202.77 } # Allow servers from SSLabs more connection requests
# Crowdsec bouncer
table <crowdsec-blacklists> persist
# table <crowdsec6-blacklists> persist
### OPTIONS ###
set skip on lo0
set block-policy drop
set loginterface $ext_if
set limit table-entries 400000
### NORMALIZATION ###
scrub in all no-df fragment reassemble max-mss 1440 # Scrub for all incoming packets
scrub out all random-id # Randomize the ID field for all outgoing packets
### QUEUEING ###
altq on $ext_if cbq bandwidth 50Mb queue { q_default q_flooders }
queue q_default bandwidth 99% cbq(default borrow)
queue q_flooders bandwidth 1%
### TRANSLATION ###
nat on $ext_if from !($ext_if) -> ($ext_if) # Wireguard
antispoof quick for $ext_if # Apparently a good thing
### FILTERING ###
block all # By default all traffic is blocked and NOT logged unless explicitly stated otherwise.
pass in quick log on $ext_if proto tcp from { <home> } to port $TCP_EXT_OK $TCP_STATE queue q_default # More liberate access from inside home network
pass in quick log on $ext_if proto udp from { <home> } to port $UDP_EXT_OK queue q_default
pass in quick log on $vpn_if to any $TCP_STATE queue q_default # Allow traffic from Wireguard interface - no restrictions
block in quick log on $ext_if from { <martians>, <pfbadhost>, <crowdsec-blacklists> } label "block.in" # Block traffic from/to forbidden addresses.
block out quick log on $ext_if to { <martians>, <pfbadhost>, <crowdsec-blacklists> } label "block.out" # Block traffic from/to forbidden addresses.
block in quick log on $ext_if from { no-route, urpf-failed } # Block bogus incoming traffic.
pass in quick log on $ext_if proto udp to port $UDP_EXT_OK queue q_default # Allow access to services - UDP
pass in quick log on $ext_if proto tcp from { <flooders> } to port $TCP_EXT_OK $TCP_STATE queue q_flooders
pass in quick log on $ext_if proto udp from { <flooders> } to port $UDP_EXT_OK queue q_flooders # Allow access to services - <badhosts> - ALTQ - minimum bandwith TCP and UDP
pass in quick log on $ext_if proto tcp from { <sslabs> } to port { https } $TCP_STATE queue q_default # Allow SSLabs to hammer port 443 for scanning
# TODO: Add priority queue for ALTQ
pass in quick log on $ext_if proto tcp to port $TCP_EXT_OK $TCP_STATE \
(max-src-conn 100, max-src-conn-rate 30/1, \
overload <flooders> flush global) \
queue q_default # General rule for all TCP access
# Allow traffic from home - should be get highest priority with ALTQ
# pass in quick on $ext_if proto tcp from { <dns:fritz> } to port $TCP_EXT_OK $TCP_STATE queue q_default
# pass in quick on $ext_if proto udp from { <dns:fritz> } to port $UDP_EXT_OK queue q_default
# Allow NS from unspecified to solicited node multicast address (DAD).
# pass quick inet6 proto icmp6 from :: to $MC_SOLNOD icmp6-type neighbrsol no state
pass quick inet proto udp from 0.0.0.0 port bootpc to 255.255.255.255 port bootps no state # Allow BOOTP/DHCP DISCOVER.
# Allow IPv6 Router Discovery (RA in / RS out).
# pass in quick inet6 proto icmp6 from $PFX_LNKLOC to $MC_NODLNK icmp6-type routeradv no state
# pass out quick inet6 proto icmp6 from ($ext_if) to $MC_RTRLNK icmp6-type routersol no state
# Allow IPv6 Neighbor Discovery (ND/NUD/DAD).
# pass in quick inet6 proto icmp6 from { $PFX_LNKLOC, ($ext_if:network) } to { ($ext_if), $MC_SOLNOD } icmp6-type neighbrsol no state
# pass in quick inet6 proto icmp6 from { $PFX_LNKLOC, ($ext_if:network) } to { ($ext_if), $MC_NODLNK } icmp6-type neighbradv no state
# pass out quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv } no state
# pass inet6 proto ipv6-icmp all icmp6-type neighbradv
# pass quick inet6 proto icmp6 icmp6-type echoreq
pass quick inet proto icmp icmp-type echoreq # Allow ping/ping6 in both directions (in/out).
pass out on $ext_if to any queue q_default # Allow all outbound traffic (for now)
pass out on $vpn_if to any queue q_default # vpn wg0
pass out on $gsd_if to any queue q_default # vpn wg-gsd
# Allow outbound traffic through restricted ports
# pass out log on $ext_if proto tcp to port $TCP_OUT_OK $TCP_STATE
# pass out log on $ext_if proto udp to port $UDP_OUT_OK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment