Jul 22 - Update protect admin page with fail2ban

This commit is contained in:
2026-07-22 16:41:08 -04:00
parent ade7c5b33c
commit 8533cbe27c
9 changed files with 254 additions and 23 deletions
+49
View File
@@ -179,3 +179,52 @@ Then visit `https://your-domain/admin`, sign in, and manage content.
- `SECRET_KEY` must be stable and secret; changing it logs everyone out.
- The admin routes live under `/admin`; the public page and `schema.sql` SQL
workflow above still work unchanged.
---
## Brute-force protection (fail2ban)
Every login attempt is written to `logs/auth.log` (rotating, 1 MB × 5) with the
real client IP:
```
2026-07-22 12:00:00,123 jqc.auth WARNING FAILED LOGIN user=admin from 203.0.113.5
2026-07-22 12:00:05,456 jqc.auth INFO LOGIN OK user=admin from 203.0.113.5
```
The real IP comes from `ProxyFix` reading nginx's `X-Forwarded-For` (gunicorn
binds 127.0.0.1, so the header can't be spoofed from outside). Config ships in
`deploy/fail2ban/`.
### Install
```bash
sudo apt-get install -y fail2ban
sudo cp deploy/fail2ban/filter.d/jqc-admin.conf /etc/fail2ban/filter.d/
sudo cp deploy/fail2ban/jail.d/jqc-admin.local /etc/fail2ban/jail.d/
# edit logpath in the jail file if your app dir differs from /home/jqc/jqc_features
sudo systemctl enable --now fail2ban
sudo systemctl restart fail2ban
```
Default policy: **5 failures in 10 min → 1 h ban** (`maxretry`/`findtime`/`bantime`
in the jail file).
### Verify
```bash
# regex matches the log lines:
sudo fail2ban-regex logs/auth.log deploy/fail2ban/filter.d/jqc-admin.conf
# jail is live:
sudo fail2ban-client status jqc-admin
```
`fail2ban-regex` should report matches equal to the number of `FAILED LOGIN`
lines. `status` shows currently banned IPs.
### Scope note
This jail bans credential-guessing that reaches the password check (a real
browser session with a valid CSRF token). Dumb bots that POST without a CSRF
token get an HTTP 400 and never reach the check — they can't guess a password
anyway. To also throttle those, add an nginx `limit_req` on `/admin/login`.