Block abusive IPs after repeated failed plan lookups

Port 79 mostly attracts HTTP/SIP probes, TLS handshakes, and username
guessers -- none of which resolve to a plan file. Treat any request that
fails to read a plan as an "offense" and timestamp it against the source
IP.

Add BanTracker (ban.hpp/ban.cpp): a per-IP rolling-window offender list.
When an IP has more than 3 offenses still inside a 24h window, its
connections are dropped without being read or answered; timestamps older
than the window are pruned so a blocked IP frees itself automatically.
State is in-memory (single io_context thread, no locking); the clock is
injected for testability. A periodic sweeper keeps the map bounded.

Legitimate lookups that hit a real plan never count, which also
frustrates username enumeration. Unit tests in test_ban.cpp.
This commit is contained in:
pmb
2026-06-15 16:23:58 -07:00
parent 268ededc19
commit 946c2b9e01
6 changed files with 264 additions and 7 deletions
+10
View File
@@ -59,3 +59,13 @@ and execute `docker compose up -d`
# Setting your status
within the `./users` directory, create a file named after the user you wish to have a response. That's it!
# Abuse protection
Most traffic on port 79 is not finger at all -- HTTP and SIP probes, TLS
handshakes, and username-guessing scanners. None of these resolve to a plan
file, so the daemon treats any request that fails to read a plan as an
"offense" and timestamps it against the source IP. When an IP records more than
3 failures within a rolling 24-hour window, its connections are dropped
(without being read or answered) until those failures age back out of the
window. Legitimate lookups that hit a real plan never count against an IP. All
state is in-memory; thresholds live in `BanTracker::Config` (`ban.hpp`).