SAM is a small Linux command-line tool for persistent IPv4 and IPv6 source bans. It can block an address or CIDR across the whole server, or restrict the ban to selected public ports and TCP/UDP protocols. Its nftables prerouting hook runs before destination NAT, so bans cover normal host services and Docker-published ports.
- Complete inbound source blocks or port-scoped blocks
- IPv4, IPv6, and CIDR networks
- Comma-separated addresses, ports, and inclusive port ranges
- TCP, UDP, or both (the default)
- Permanent and automatically expiring bans
- Atomic multi-source changes
- Persistence across reboots through systemd
- Protection for Docker-published ports using the public host port
- SSH self-lockout detection and explicit confirmation
- Rule IDs, comments, status checks, JSON output, Bash completion, and a man page
- Confirmed, root-only reset to a clean state
- A Linux distribution with systemd
- Python 3.8 or newer
- nftables and the
nftcommand - Root access for installation and firewall changes
Ubuntu and Debian are the primary supported platforms. SAM is independent of UFW and does not enable, disable, or modify UFW.
Download the .deb and SHA256SUMS files from the latest GitHub release, then:
sha256sum -c SHA256SUMS --ignore-missing
sudo apt install ./sam_1.1.0_all.debgit clone https://github.com/mad-gamer26/sam.git
cd sam
sudo ./install.shThe installer preserves /etc/sam/rules.json during upgrades.
# Block one source server-wide
sudo sam ban 203.0.113.7
# Block several addresses and networks atomically
sudo sam ban 203.0.113.7,198.51.100.25,2001:db8::/48
# Block TCP and UDP on selected public ports for 12 hours
sudo sam ban 203.0.113.7 -p 22,80,443,8000-8010 -d 12h -c "abusive client"
# Limit a rule to TCP
sudo sam ban 198.51.100.25 -p 22 --protocol tcp
# Inspect and remove bans
sam list
sam check 203.0.113.7 -p 443 --protocol tcp
sudo sam unban 203.0.113.7
sudo sam unban --id a1b2c3d4When --protocol is omitted, a port-scoped ban covers both TCP and UDP. When
--ports is omitted, SAM drops all inbound IP traffic from that source.
Durations accept s, m, h, d, and w, such as 30s, 15m, 12h,
7d, or 2w. A ban without a duration is permanent.
If a proposed rule includes the client IP and server port of the current SSH
session, SAM warns that remote access may be lost and requires typing yes.
Non-interactive use is refused unless --force is supplied:
sudo sam ban 203.0.113.7 --forceKeep an independent console or recovery method available when administering a remote firewall.
Remove all active and expired bans and return SAM to an enabled clean state:
sudo sam resetThe interactive prompt requires typing reset. Automation must explicitly use
sudo sam reset --force.
| Command | Purpose |
|---|---|
ban, block |
Add one or more bans |
unban, remove |
Remove bans by exact source or rule ID |
list, ls |
List active bans (--all, --json) |
check |
Check whether an address and optional port/protocol are banned |
status |
Show configuration, counts, and runtime state |
restore, reload |
Validate and reload saved rules |
prune |
Remove expired stored bans immediately |
reset |
Remove every ban and restore an enabled clean state |
enable, disable |
Toggle enforcement without deleting stored bans |
Use sam --help, sam COMMAND --help, or man sam for full details.
SAM owns only table inet sam. Its base chain hooks into prerouting at
priority -200, before Docker's destination NAT. A port therefore refers to
the public host port, not the internal container port. For a mapping such as
8081:8080, ban port 8081.
Configuration is written atomically. The nftables syntax is validated before the live table is replaced, and the previous table is restored if application fails.
Installed files:
| Path | Purpose |
|---|---|
/usr/local/bin/sam |
CLI program |
/etc/sam/rules.json |
Persistent configuration |
/etc/systemd/system/sam.service |
Boot restoration |
/etc/systemd/system/sam-prune.{service,timer} |
Expiration cleanup |
/etc/bash_completion.d/sam |
Bash completion |
/usr/local/share/man/man8/sam.8 |
Manual page |
The Debian package follows distribution policy by installing the executable
and shared data under /usr instead; behavior and configuration paths are the
same.
make check
./scripts/build-deb.shThe Debian package is written to dist/. GitHub Actions tests every push and
pull request. Tags such as v1.1.0 build a source archive, Debian package, and
SHA-256 checksum file and publish them as a GitHub release.
sudo ./uninstall.shThis preserves /etc/sam. To permanently delete configuration as well:
sudo ./uninstall.sh --purgeMIT. See LICENSE.