- TypeScript 79.1%
- HTML 20.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| cli | ||
| core | ||
| daemon | ||
| ipc | ||
| server | ||
| tests | ||
| tools | ||
| .gitignore | ||
| banmachine-server.service | ||
| banmachine.service | ||
| config-example.json | ||
| deno.json | ||
| deno.lock | ||
| plan.md | ||
| README.md | ||
| session-ses_1430.md | ||
| specification.md | ||
BanMachine
A lightweight, modern security daemon designed to monitor structured JSON logs (like Caddy) and enforce bans via nftables.
Features
- JSON-First: Native support for structured logs.
- Sliding Window: Intelligent rate limiting.
- Persistent: State saved in SQLite.
- Non-Root: Designed to run with minimal capabilities (
CAP_NET_ADMIN). - IPC Interface: Command-line tool to manage the daemon as a regular user.
Setup Instructions
1. Create System User
Create a dedicated user for BanMachine:
sudo useradd -r -s /usr/sbin/nologin banmachine
2. Prepare Directory
Move the project to a permanent location (e.g., /opt/banmachine) and set permissions:
sudo mkdir -p /opt/banmachine
sudo cp -r . /opt/banmachine
sudo chown -R banmachine:banmachine /opt/banmachine
3. Log & Socket Access
- Add the
banmachineuser to the group that has read access to your logs (usuallyadmorlog):sudo usermod -aG adm banmachine - To allow your current user to use the CLI, add yourself to the
banmachinegroup:
(Note: You may need to log out and back in for group changes to take effect.)sudo usermod -aG banmachine $USER
4. Configuration
Edit /opt/banmachine/config.json to match your log files and rules. Ensure the ipc.socketPath is in a directory writable by the banmachine user (e.g., /tmp/banmachine.sock).
5. Install Systemd Services
- Edit
banmachine.serviceandbanmachine-server.serviceand ensure theExecStartpath todenois correct (which deno). - Copy the service files:
sudo cp banmachine.service banmachine-server.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable banmachine sudo systemctl enable banmachine-server sudo systemctl start banmachine sudo systemctl start banmachine-server
6. Viewing Logs
Since BanMachine runs as systemd services, you can view the logs using journalctl:
# Follow daemon logs in real-time
sudo journalctl -u banmachine.service -f
# Follow dashboard logs in real-time
sudo journalctl -u banmachine-server.service -f
Usage
Rule Matching
Rules select log entries via the match object. Each key is a dot-notation path into the JSON log entry, each value is a condition:
"match": {
"status": [400, 401, 403, 404],
"request.method": ["GET", "POST", "HEAD"],
"request.uri": { "$regex": "\\.(php|env|git)$" }
}
- Plain value (
404,"POST"): field equals the value. Types are coerced, so"404"in config matches404in the log. - Array: matches if the field equals any member (implicit OR). This replaces fail2ban-style alternations like
(400|401|403|404). {"$regex": "..."}: field's string value satisfies the pattern (compiled at config load; invalid patterns fail startup).{"$not": <condition>}: negates the inner condition, e.g.{"$not": {"$regex": "^/api/"}}.
A fail2ban rule like ^<HOST> -.*(GET|POST|HEAD).*" (400|401|403|404).*$ translates to:
"match": {
"status": [400, 401, 403, 404],
"request.method": ["GET", "POST", "HEAD"]
}
with <HOST> handled by the rule's ipKey.
Command Line Interface
Manage the daemon using the CLI task. You can run this as a regular user if you are in the banmachine group.
# Check status
deno task cli status
# Manually ban an IP
deno task cli ban 1.2.3.4 3600
# Manually unban an IP
deno task cli unban 1.2.3.4
Web Dashboard
If the banmachine-server service is running, the dashboard is available at:
http://localhost:8080 (or the port configured in the server).
nftables Verification
To see the rules being created by the daemon:
sudo nft list table inet banmachine
To see currently banned IPs:
sudo nft list set inet banmachine blacklist