Skip to content
cansarihanPublic

About

Single packet authorization gate: guarded ports stay closed until one authenticated UDP knock opens them for a short lease

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

cordon

CI CodeQL Go report card Go 1.25 MIT

Cordon is a single packet authorization gate. It keeps guarded ports closed and opens one only when it receives a single authenticated UDP packet — a knock — from a client that holds the shared secret. The gate never replies, so to a scanner the port is simply not there. A correct knock opens the requested port for the source address for a short lease, and the lease expires on its own.

One binary, standard library only. It runs unprivileged with an in-process firewall by default, and drives nft, pf or iptables when you ask it to.

On the command line

A cordon gate accepting two knocks from the client

$ cordon serve -secret "$CORDON_SECRET" -ports 22,443 -ttl 30s
$ cordon knock  -to gate.example.com:62201 -secret "$CORDON_SECRET" -port 22
knock sent to gate.example.com:62201: port 22, nonce 882533eb

The knock is 59 bytes: a version, a random nonce, a timestamp, the requested port, and an HMAC-SHA256 tag over the rest. The gate verifies the tag in constant time, rejects a stale timestamp, rejects a nonce it has already seen, and — only then — opens the port.

The panel

The console shows the gate as a checkpoint. The barrier is down and the lamp red while the gate is secured; a valid knock lifts the barrier, turns the lamp green, and drops a lease onto the requested port with a live countdown. Denied knocks land in the ledger with their reason — a bad tag, a stale packet, a replay, or a port that is not on the allow-list.

The secured gate: barrier down, every port closed

Three open leases: barrier up, ports counting down, denials in the ledger

Run the demo

The demo runs a gate with the in-process firewall and a client that knocks on a loop — valid knocks on the allowed ports, and a couple of bad ones so you can watch them be turned away.

make demo          # panel at http://127.0.0.1:18210
make demo-down

Install

go install github.com/cansarihan/cordon/cmd/cordon@latest

or build from source:

git clone https://github.com/cansarihan/cordon
cd cordon
make build         # ./bin/cordon

Guarding a real port

By default the gate tracks leases in process and touches nothing on the host. To open an actual port, give it a shell template for open and close; {ip} and {port} are substituted before the command runs.

cordon serve -secret "$CORDON_SECRET" -ports 22 \
  -open  "nft add element inet filter cordon { {ip} }" \
  -close "nft delete element inet filter cordon { {ip} }"

Set up the nft set once and add the accept rule that reads it; the templates only add and remove members. configs/firewall-templates.md has the nft, pf and iptables recipes, and configs/cordon.service is a systemd unit that runs the gate with CAP_NET_ADMIN and nothing else.

Commands

cordon serve   -listen 127.0.0.1:8080 -knock 0.0.0.0:62201 -secret ... -ports 22,443 -ttl 30s
cordon knock   -to host:62201 -secret ... -port 22
cordon version

serve flags: -window (accepted clock skew, default 30s), -reap (lease sweep interval, default 5s), -open/-close (shell templates; presence switches on the shell backend). The secret can also come from CORDON_SECRET.

Design

  • Default closed. Nothing is open until a knock opens it, and every lease expires on its own.
  • Silent. The gate never answers a packet, so it gives a scanner no signal.
  • Authenticated and fresh. HMAC-SHA256 over the packet, a constant-time compare, a timestamp window, and a nonce cache against replay.
  • Unprivileged by default. The in-process firewall needs no root; the shell backend is opt-in.

docs/architecture.md explains how the pieces fit together.

License

MIT — see LICENSE.

About

Single packet authorization gate: guarded ports stay closed until one authenticated UDP knock opens them for a short lease

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages