# /etc/pf.conf — edge box default-deny + nat + WG passthrough # # Layout: # egress = WAN-side NIC (public IP from ISP/router) # lan = LAN-side NIC (192.168.0.0/24, internal LAN) # wg0 = WireGuard tunnel to nullstone (private /29 subnet, e.g. 10.10.10.0/29) # # Adjust interface names per `ifconfig` output on the T5600 (likely em0+em1). # === Macros === ext_if = "em0" # WAN-side int_if = "em1" # LAN-side wg_if = "wg0" nullstone = "10.10.10.2" # nullstone over WG; edge is 10.10.10.1 # === Tables === # Bogus / non-routable; martians; tor-exit if you want to block (left empty) table persist file "/etc/pf-bogons" table persist # === Options === set skip on lo set block-policy drop set loginterface egress set syncookies adaptive (start 25%, end 12%) # === Normalisation === match in all scrub (no-df random-id max-mss 1440) # === Default deny === block in log all block out log all pass out quick on $ext_if from ($ext_if:0) keep state # === Anti-spoof / bogon drop on WAN === antispoof quick for { $ext_if $int_if } block in quick on $ext_if from to any block in quick on $ext_if from any to # === Inbound: 80/443 ports → relayd → backend over wg0 === # relayd binds to ($ext_if) on these ports; pass traffic to it explicitly. pass in on $ext_if proto tcp to ($ext_if) port { 80 443 } \ flags S/SA modulate state \ (max-src-conn 100, max-src-conn-rate 60/10, \ overload flush global) # === Inbound SSH: rate-limit + bruteforce trap === pass in on $ext_if proto tcp to ($ext_if) port 22 \ flags S/SA modulate state \ (max-src-conn 5, max-src-conn-rate 3/30, \ overload flush global) block in quick from # === WireGuard: allow UDP 51820 from anywhere (handshake) === pass in on $ext_if proto udp to ($ext_if) port 51820 keep state # === Tunnel traffic: pass freely between edge and nullstone === pass on $wg_if all keep state pass quick proto { tcp udp icmp } from $nullstone to ($wg_if) keep state # === LAN side: trust LAN, allow outbound + DNS to unbound === pass on $int_if all keep state # === ICMP for path-MTU + diagnostics === pass inet proto icmp icmp-type { echoreq unreach timex } keep state # === Logging === # `pflog0` interface captures matched-`log` rules. tcpdump -ni pflog0 to watch.