Skip to main content

macOS PF (Packet Filter) firewall configuration TUI

Project description

wj-firewall

A macOS PF (Packet Filter) firewall configuration tool with both an interactive terminal UI and a command-line interface.

wj-firewall is not a firewall itself — it configures macOS's built-in PF packet filter. It makes it easy to block incoming traffic on specific network interfaces while keeping others open. The typical use case is blocking incoming connections on Wi-Fi while keeping Tailscale or other trusted networks open, so services listening on 0.0.0.0 are only reachable from trusted networks.

Features

  • Interactive TUI — curses-based terminal UI for visual interface management
  • CLI — scriptable command-line interface for automation and quick changes
  • Per-interface blocking — block incoming traffic on selected interfaces
  • Port exceptions — allow specific ports through on blocked interfaces (TCP + UDP)
  • ICMP control — optionally block ICMP (ping, traceroute) on blocked interfaces
  • PF anchors — rules stored in /etc/pf.anchors/wj-firewall, surviving OS updates
  • Zero dependencies — Python 3.12+ stdlib only

Requirements

  • Python 3.12+
  • macOS (uses PF and pfctl)
  • Administrator privileges (sudo) for applying firewall rules

Installation

pip install wj-firewall

Or run directly with uv:

uvx wj-firewall

Quick Start

Interactive TUI

wj-firewall

You will be prompted for your password (sudo). The TUI shows all network interfaces and lets you:

  • Space — toggle "block incoming" on the selected interface
  • p — open port editing mode (add/remove port exceptions)
  • i — toggle ICMP blocking on a blocked interface
  • a — apply changes (writes anchor file and reloads PF)
  • r — revert to last applied state
  • q — quit (confirms if unsaved changes)

Command-Line Interface

# Show current firewall status
wj-firewall status

# Block incoming traffic on Wi-Fi
wj-firewall block en0

# Allow SSH and HTTP through on a blocked interface
wj-firewall allow en0 22 80

# Block ICMP (ping) on an interface
wj-firewall icmp en0 block

# Remove a port exception
wj-firewall deny en0 80

# Unblock an interface
wj-firewall unblock en0

How It Works

wj-firewall uses macOS PF anchors to manage firewall rules without touching the rest of your pf.conf. Rules are stored in /etc/pf.anchors/wj-firewall and referenced from pf.conf via anchor declarations. The tool automatically adds the anchor references if they are missing.

For each blocked interface, the following PF rules are generated:

  1. Pass outgoing — all outbound traffic and return traffic is allowed
  2. Pass DHCP — DHCP discovery is always allowed (so you can get an IP address)
  3. Pass ICMP — ping, traceroute, and PMTU discovery are allowed (unless ICMP is blocked)
  4. Pass ports — any port exceptions are allowed through (both TCP and UDP)
  5. Block everything else — all other incoming traffic is silently dropped

Rules use quick for first-match-wins evaluation and block drop (silent discard) to avoid triggering macOS Private Relay issues.

Development

# Set up development environment
make dev

# Run linting and type checking
make check

# Auto-format code
make format

# Build wheel and docs
make build

Licence

Released under the Unlicense — public domain.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wj_firewall-1.0.0b3-py3-none-any.whl (40.8 kB view details)

Uploaded Python 3

File details

Details for the file wj_firewall-1.0.0b3-py3-none-any.whl.

File metadata

  • Download URL: wj_firewall-1.0.0b3-py3-none-any.whl
  • Upload date:
  • Size: 40.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for wj_firewall-1.0.0b3-py3-none-any.whl
Algorithm Hash digest
SHA256 7485f75b4cfb2e7c948c20a8df67c2da1b759866d7a363fac4b123810ed44c0e
MD5 75642fc968e44b8387ded4025f83865b
BLAKE2b-256 bac169fb28ab7df0845a74f65c0eacd2978421691be29311dbc4ee8c596ca596

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page