Usage
wj-firewall provides two interfaces: an interactive terminal UI (TUI) and a command-line interface (CLI). Both read from and write to the same PF anchor file, so changes made in one are visible in the other.
Interactive TUI
Launch the TUI by running wj-firewall with no arguments:
wj-firewall
Or via module:
python -m wj_firewall
You will be prompted for your password (sudo) before the TUI appears.
Layout
The TUI displays:
- Title bar — application name, version, and a hint to run
wj-firewall --helpfor CLI usage - Status indicators — whether PF is enabled, anchor is configured, and boot persistence is active
- Interface table — all detected network interfaces with their IP addresses and firewall state
- Help bar — available key bindings
- Status area — feedback messages after actions
Interface Table Columns
| Column | Description |
|---|---|
| Interface | System name and description (e.g. en0 (Wi-Fi)) |
| IP Address | IPv4 address, or [IPv6] if only IPv6 is assigned |
| Incoming | BLOCKED (red) or allowed (dim) |
| ICMP | block (red) if ICMP is blocked on a blocked interface |
| Open Ports | Comma-separated list of allowed port numbers |
Key Bindings
| Key | Action |
|---|---|
↑ / k |
Move cursor up |
↓ / j |
Move cursor down |
Space |
Toggle block incoming on the selected interface |
p |
Enter port editing mode (only on blocked interfaces) |
i |
Toggle ICMP blocking (only on blocked interfaces) |
a |
Apply changes — write anchor file and reload PF |
r |
Revert — discard changes and restore last applied state |
q |
Quit (prompts for confirmation if there are unsaved changes) |
Port Editing Mode
Press p on a blocked interface to enter port editing mode. The help bar changes to a port input prompt:
Port: ___█ (Enter=toggle i=ICMP Esc=cancel)
- Type a port number (1–65535) and press Enter to toggle it (add if absent, remove if present)
- Press i to toggle ICMP blocking without leaving port editing mode
- Press Esc to exit port editing mode
- The mode stays open after each port toggle for quick multi-port entry
Applying Changes
Changes in the TUI are not written to disk until you press a (Apply). This writes the anchor file, ensures pf.conf references the anchor, enables PF if needed, installs a launch daemon to re-enable PF at boot, and reloads the ruleset.
If PF is disabled or the anchor is missing from pf.conf, pressing a will fix both automatically.
Command-Line Interface
The CLI provides subcommands for scripting and quick one-off changes. All commands that modify rules require sudo.
status — Show current state
wj-firewall status
Displays a table of all network interfaces with their block state, ICMP state, and open ports. Also shows whether PF is enabled, whether the anchor is configured, and whether the boot launch daemon is installed. Requires sudo.
block — Block incoming traffic
wj-firewall block en0
wj-firewall block en0 en1
Blocks incoming traffic on one or more interfaces. If the interface is already blocked, no change is made. Applies immediately.
unblock — Remove blocking
wj-firewall unblock en0
Removes blocking from an interface. Also clears any port exceptions and ICMP settings for that interface. Applies immediately.
set — Set exact blocked list
wj-firewall set en0 en1 # Block exactly en0 and en1
wj-firewall set # Unblock everything
Sets the blocked interface list to exactly the given interfaces. Any previously blocked interfaces not in the list are unblocked. Preserves port exceptions and ICMP settings for interfaces that remain blocked.
allow — Open ports
wj-firewall allow en0 22
wj-firewall allow en0 22 80 443
Opens specific ports on a blocked interface. If the interface is not already blocked, it will be blocked first. Both TCP and UDP pass rules are generated for each port. Applies immediately.
deny — Close ports
wj-firewall deny en0 80
wj-firewall deny en0 80 443
Removes port exceptions from a blocked interface. Applies immediately.
icmp — Control ICMP
wj-firewall icmp en0 block # Block ICMP (ping, traceroute)
wj-firewall icmp en0 allow # Allow ICMP (default)
By default, blocked interfaces allow ICMP through (ping, traceroute, PMTU discovery). Use icmp block to suppress all ICMP on an interface.
remove — Remove all PF modifications
wj-firewall remove
Completely removes all wj-firewall PF modifications: removes the boot launch daemon, deletes the anchor file (/etc/pf.anchors/wj-firewall), removes the anchor references from pf.conf, reloads the PF configuration, and flushes states on previously blocked interfaces. This is the inverse of applying rules — it leaves PF in a clean state as if wj-firewall had never been used. PF remains enabled for the current session but will not auto-enable on next reboot.
Safe to run if already removed (reports what is already clean and exits successfully).
Common Options
All subcommands support:
--no-colour/--no-color— disable coloured terminal output--help— show help for the subcommand
Privilege Requirements
- All CLI subcommands require sudo. The CLI relaunches itself under
sudoif needed. - TUI prompts for sudo credentials before entering curses mode, so the password prompt appears in the normal terminal.
Generated PF Rules
For a blocked interface en0 with ports 22 and 80 allowed and ICMP permitted (default), the generated anchor file contains:
# en0 — block incoming (22, 80)
pass out quick on en0 all keep state
pass in quick on en0 proto udp from any port 67 to any port 68 keep state
pass in quick on en0 proto icmp all keep state
pass in quick on en0 proto tcp from any to any port 22 keep state
pass in quick on en0 proto udp from any to any port 22 keep state
pass in quick on en0 proto tcp from any to any port 80 keep state
pass in quick on en0 proto udp from any to any port 80 keep state
block drop in quick on en0 all
If ICMP is blocked, the pass in ... proto icmp line is omitted. The comment changes to (no ICMP, 22, 80).