Abusive HTTP Watch is a lightweight OpenBSD daemon that tails the
web server access log in real time, detects malicious HTTP probes
against a curated token set, and writes the offending source IPs to a
file that can be consumed directly by the firewall (e.g. pf).
In active production protecting web shops.
| Property | Value |
|---|---|
| Version | 2.1.2 |
| Platform | OpenBSD (RC script integration) |
| Language | Perl 5 (standard library only) |
| Use case | Web shop hardening |
| Status | Running in production |
flowchart LR
A[Webserver logs] --> B[Pattern match]
B --> C{"Threshold hit?"}
C -->|Yes| D[PF block rule]
C -->|No| A
D --> E[(Block table)]
E -->|TTL expired| F[Auto release]
Web shops and production websites are constantly probed for
vulnerabilities — PHP exploits, WordPress login probes,
/etc/passwd lookups, path traversal, SQLi, null-byte injection.
These probes leave a clear token pattern in the access log,
regardless of the HTTP status code returned.
Abusive HTTP Watch tails the log, evaluates each line against a
precise token set, and writes IPs with repeated hits into an
append-only blocklist that drops straight into OpenBSD pf tables,
Apache Require directives, or nginx deny lists.
The token set targets attack classes that demonstrably show up in production logs — deliberately conservative to avoid false positives.
allow_url_include, auto_prepend_file, php://input, eval(wp-admin, wp-login.php and variants../.. plus common encodings.env, .git, .svn, id_rsa, /etc/passwdcgi-bin, ?cmd=, =shell, eval(or 1=1 and conservative variantsback= parameters, including URL-encoded%00 in URIpos > size) and recovers without missing lines.203.0.113.0/24, 2001:db8::/32).request, user-agent, and optionally referrer. Referrer scope is off by default to prevent drive-by blocks via third-party pages.flock(LOCK_EX) on writes, in-memory dedup prevents duplicate entries across restarts./etc/abusive_http_whitelist accepts single IPs or CIDRs that are always let through.MIN_HITS hits (default 3) is an IP added to the blocklist — protects against accidental singletons.tag, facility, prio configurable via env) for added actions and diagnostics.Fully controllable via environment variables — no code change required.
| Variable | Purpose | Default |
|---|---|---|
ABUSIVE_FAMILY | IP family filter (v4/v6/any) | any |
ABUSIVE_MIN_HITS | Hit threshold before blocking | 3 |
ABUSIVE_SCOPE | Fields to match (request,ua,referrer) | request,ua |
ABUSIVE_REFERRER_DOMAINS | Allowed referrer hosts | — |
ABUSIVE_SYSLOG_TAG | Syslog tag | abusive_http_watch |
ABUSIVE_SYSLOG_FACILITY | Syslog facility | daemon |
ABUSIVE_SYSLOG_PRIO | Syslog priority | notice |
ABUSIVE_DEBUG | Enable debug output | 0 |
Deliberately minimal — only OpenBSD base tools and Perl standard modules.
| Component | Role |
|---|---|
OpenBSD rc.d | Daemon lifecycle (start/stop/reload) |
| Perl 5 | Runtime — stdlib only (Fcntl, IO::Handle, Sys::Syslog, Socket) |
pf | Firewall consumer of the blocklist (<abusive> table) |
syslogd | Central event aggregation |
newsyslog | Log rotation — handled transparently by the watcher |
Abusive HTTP Watch — Version 2.1.2 · OpenBSD rc.d daemon · in production at web shops · ~380 SLOC pure Perl