FreeBSD PF-based ORPort protection for Tor relays.
orport-guard keeps Tor relay DDoS mitigation small and inspectable:
- discovers relay listeners from Tor config
- falls back to
sockstatwhen needed - rewrites public targets to the PF-visible local address on NATed hosts when that mapping is unambiguous
- fetches Tor authority and Snowflake trust lists
- renders one dedicated PF anchor instead of owning the whole firewall
- refreshes trust tables and expires block entries without reloading the full ruleset every time
Download the latest standalone release artifact:
curl -fsSLo orport-guard https://github.com/MinorGlitch/orport-guard/releases/latest/download/orport-guard
chmod +x ./orport-guard
./orport-guard --helpUpdate that standalone script later with:
./orport-guard updateCommands that need PF or crontab access will try to re-run themselves through doas, then sudo, if you did not elevate them first.
Typical first install:
./orport-guard check
./orport-guard enable
./orport-guard statusWhat those do:
checkdiscovers targets and validates the rendered PF anchor without touching live PFenableinstalls the root PF hook if needed, reloadspf.conf, and loads the managed anchorstatusshows the live anchor state, detected targets, trust/block counts, and recent refresh/expire timestamps
If you want exact expiry cleanup and periodic trust refresh:
./orport-guard install-cronThat installs:
expireevery minuterefreshevery 6 hours
Useful day-2 commands:
./orport-guard apply
./orport-guard refresh
./orport-guard expire
./orport-guard disable
./orport-guard remove-cronapplyreloads only the managed anchor after the PF root hook already existsrefreshupdates trust tables onlyexpireremoves old blocked entries immediatelydisableunloads the managed anchor and flushes its tablesremove-cronremoves only the managed cron block
orport-guard manages one PF anchor:
anchor "orport-guard"
enable installs that hook automatically when it is missing. If you need to do it manually:
./orport-guard install-hook
pfctl -nf /etc/pf.conf
pfctl -f /etc/pf.confOn NATed VPS setups, PF often sees the local post-NAT address instead of the public relay IP. orport-guard tries to detect that automatically. If there are multiple possible local addresses, it refuses to guess.
When inspecting live state, use anchor-scoped PF commands:
doas pfctl -a orport-guard -vvs rules
doas pfctl -a orport-guard -s Tables
doas pfctl -a orport-guard -t orport_guard_trust_v4 -T show | wc -l
doas pfctl -a orport-guard -t orport_guard_block_v4 -T show | wc -lIf you need to confirm what PF is actually seeing on FreeBSD, use tcpdump on the real interface, not any:
ifconfig -l
doas tcpdump -ni <interface> 'port <orport>'For the full CLI surface, use:
./orport-guard --helpFor local development from the repo instead of the release artifact:
./bin/orport-guard --help