A live stdin filter for SSH authentication failures on an Ubuntu server. The
implementation is kept in main.go.
- Read one journal JSON object per line from stdin.
- Count each
MESSAGEcontaining aFailed password for ... from IPv4 ...record once. PAM authentication failures and other SSH messages do not count. - Use processing time to count failures per IPv4 address in a rolling 60-second window. The default threshold is three records.
- Never ban loopback, private, link-local, non-global-unicast, or explicitly trusted IPv4 addresses.
- Once an address reaches the threshold, check for the exact
iptablesINPUT/DROPrule before adding it. Rules are permanent and must be removed manually. Existing firewall rules are the source of truth; no ban state is persisted by the program.
Malformed JSON lines are logged and skipped. Input read errors and firewall
command failures are reported and stop the process. The program must run as root
to enforce bans; it invokes iptables directly without sudo.
Build the executable:
go build -o drop3 .Run with a live journal stream:
sudo sh -c 'journalctl -f -o json -u ssh.service | ./drop3'
sudo sh -c 'journalctl -f -o json -u ssh.service | ./drop3 -window 5m'
sudo sh -c 'journalctl -f -o json -u ssh.service | ./drop3 -window 6m -threshold 2'Test parsing and threshold behavior without changing firewall rules:
go run . -dry-run < test/NDJSON.jsonOptions:
-threshold int failed records required to trigger a ban (default 3)
-window duration rolling counting window (default 1m)
-trusted-ips string comma-separated IPv4 addresses never to ban
-dry-run log would-be bans without invoking iptables

