Persian dežbān (دژبان) — "gatekeeper / garrison guard."
Dezhban is dedicated, humbly, to the civilians killed in Iran since December 2025 — shot, executed, or tortured to death by the state for protesting, while that same state cut the country off from the internet so the world could not watch.
dezhban makes sure your traffic can only leave this machine through your VPN. If the VPN drops, your connection is cut instantly instead of silently falling back to your real IP. If the VPN redials somewhere you've told it to refuse, everything stops. On macOS it's a menubar app you click; everywhere else, and for anyone who prefers it, it's a CLI and background service.
[ your machine ] --- VPN tunnel up ---> [ the internet ]
VPN drops: nothing to react to, the standing rule
already blocks every non-tunnel path
|
v
[ egress cut, instantly ] (a plain kill switch would leak right here)
Warning
dezhban deliberately cuts network access. A wrong VPN endpoint, a crash before
teardown, or running it over a remote session can lock you out of your own
machine. The escape hatch is the menubar app's Panic button, or
sudo dezhban panic from a terminal — either works with no daemon running.
Read docs/usage/getting-started.md before arming
it for real.
| macOS | Linux | Windows | |
|---|---|---|---|
| App | Menubar + window | — | — |
| CLI | ✅ | ✅ | ✅ (experimental) |
| Enforcement backend | pfctl |
nft |
WFP |
Windows is an early target: go vet gates it in CI, but the control socket's
whole authorization model is unix permissions, which Windows has no equivalent
of yet, so there's no passwordless path there today. Use the CLI, and expect
rough edges.
curl -fsSL https://raw.githubusercontent.com/Behnam-RK/dezhban/main/scripts/install.sh -o ~/dezhban-install.sh && sudo bash ~/dezhban-install.shDownload first, run from the file, on purpose — that way the installer can ask.
On a fresh machine at a real terminal it offers a menu: install with today's
defaults, choose components (the menubar app, and whether to register the
service), or cancel — and then whether to run the setup wizard. Re-run it on a
machine that already has dezhban and the menu is upgrade (or reinstall, if you
are on that version already), uninstall, or cancel instead. Piped into bash it takes the defaults silently. Not because a pipe
makes asking impossible — the prompts read your terminal directly — but because
a piped install is defined to be unattended here, so a provisioner or a CI job
gets the same answers every time.
The && and the home directory both matter. A failed download can leave a
stale or half-written file behind — a truncated script still runs as far as
it parses — so the two commands are chained rather than pasted as two lines.
And /tmp is world-writable under a name anyone can guess, so a file there
might not even be yours. As root.
Want to read it before running it as root, which is the right habit for a kill
switch? Run only the curl half, check it exited 0, read the file, then run the
sudo bash half — your reading is what replaces the && there. Delete
~/dezhban-install.sh afterwards either way, so a later run from muscle memory
can't pick up a stale copy. More on all of
this.
For an unattended install (a provisioner, CI, a second machine you have already decided about), the one-liner still works and takes today's defaults with no prompt:
curl -fsSL https://raw.githubusercontent.com/Behnam-RK/dezhban/main/scripts/install.sh | sudo bashThen open Dezhban from Applications (or Spotlight). Whichever form you
used, that is all the terminal work there is — not because the app can't be
double-clicked, but because there's no Apple Developer certificate to sign it
with yet, so Gatekeeper would otherwise block it. curl genuinely doesn't
trip that check (it's documented Apple behavior, not a workaround), so either
form installs the app with zero Gatekeeper friction and asks for your
password exactly once. Details, the .pkg alternative, and Linux/Windows
installers: docs/usage/install.md.
Open the app and everything else happens by clicking:
- Menubar dropdown — the safety core. One glance tells you the posture (e.g. "Guard — NL via Mullvad"); the VPN switch window with a live countdown, Pause, and Panic. These never require the main window to be open. Manual Block / Unblock are not here — they live in Overview, since anyone who wants to cut their own internet can turn off Wi-Fi.
- Overview — live status, the daily controls, and guided recovery: if the service isn't installed or is stopped, there's an inline button for exactly that, not an error message.
- Settings — a full config editor: VPN tunnel/endpoints, autodetection, blocked countries, both windows' durations, local-network access, start at boot, launch at login. One confirmation per batch of changes, not one per field.
- Logs & Diagnostics — read-only
doctor, recent logs, a live log stream. - Privileged actions (install, start/stop, panic) prompt with Touch ID where available; routine block/unblock/switch need no prompt at all.
A GUI user never needs a terminal again — including for upgrades, which the app checks for and applies in place.
Linux, servers, and anyone who prefers a terminal on any OS:
sudo dezhban setup # interactive wizard — build the config, no JSON by hand
dezhban validate # confirm it (--config is optional)
dezhban monitor # live IP/country/tunnel/verdict, no firewall touched
sudo dezhban run # run the daemon (root; drives the firewall)
sudo dezhban panic # always-available teardown, no daemon neededFull walkthrough: docs/usage/getting-started.md.
Complete command reference: docs/usage/cli.md. Tab-completion:
source <(dezhban completion zsh).
One enforcement model — the guard. What changes is the posture:
STANDBY --arm--> GUARD <==> FULL BLOCK (blocked / allowed country)
|
+--switch or redial--> SWITCH WINDOW
(bounded, self-closing)
- STANDBY — no rules, network fully open, nothing is being blocked. The resting state before any tunnel has been observed. Arms itself when a VPN connects.
- GUARD — the healthy state. Only the tunnel may carry traffic off the
machine, so a drop is cut instantly (zero leak window with
vpn.redialWindow: "0"; by default a bounded redial window follows the cut so the VPN can redial). - FULL BLOCK — the VPN's exit landed in a blocked country. All user traffic is cut, but the endpoint handshake stays open so the tunnel can recover.
- SWITCH WINDOW — the one sanctioned relaxation, bounded and self-closing, from exactly two triggers: an explicit operator command, or the automatic redial window.
Full state machine and exact rulesets: docs/concepts/modes.md.
JSON, with durations as strings (e.g. "30s"). Sample configs live in configs/
(dezhban.example.json is fully automatic; dezhban.vpn-guard.json pins the
tunnel interface and endpoints explicitly). Full field reference:
docs/usage/config.md.
See docs/README.md for the full set, grouped by audience — using it, the mental model, and contributing.
Hippocratic License 3.0 (Core) with the Dezhban named-entity restriction © 2026 Behnam RK.
This is not an OSI-approved open source license, and it is not MIT. Part A
of LICENSE withholds any grant from the IRGC, the Ministry of Intelligence,
FARAJA, and anyone who took part in or materially supported the killing of
protesters in Iran. Part B is the Hippocratic License 3.0 (Core), verbatim,
which requires derivative works to carry the same license.
