Scanner blocking

Every public site receives a steady stream of automated vulnerability probes - requests for /wp-login.php, /.env, /xmlrpc.php and friends. The bad-URL auto-blocker recognises these, counts them per source IP in a rolling window, and blocks the IP once it crosses a threshold. It is on by default.

What counts as a probe

Built-in patterns cover the common scanner noise: WordPress paths (wp-login.php, wp-admin, wp-content, xmlrpc.php), phpMyAdmin, dotfile fishing (.env, .git, .aws, .ssh), router/exploit endpoints (HNAP1, setup.cgi, boaform), Exchange and Spring paths (owa/, autodiscover, actuator) - and any .php URL at all, since a lazysite site serves no PHP. Operators can add their own substrings on top.

Configuration

Keys in lazysite/lazysite.conf, also editable on the manager's Plugin Config page:

  • bad_url_block - enabled (default) or disabled
  • bad_url_threshold - probe hits from one IP that trigger a block (default 10)
  • bad_url_window - rolling window in seconds over which hits are counted (default 3600)
  • bad_url_extra - comma-separated extra substrings to treat as probes on top of the built-ins

So by default: ten probe URLs from one IP within an hour and that IP is blocked.

Where blocks are enforced

Enforcement runs in the auth wrapper, ahead of everything else - so it protects auth-wrapped sites, covers every request through the wrapper, and a blocked IP cannot even reach the login form. A blocked IP receives a plain 403 Forbidden. Each auto-block is written to the audit trail and the error log.

When nothing is blocked the check is a single file test, so the common case costs almost nothing; with the feature disabled the module is never even loaded.

Unblocking

The manager's Visitor Statistics page shows the blocked-IP list - each entry with its first-blocked time, hit count and the probe path that tipped it - with an Unblock button per IP. The same pair of actions is available on the control API (bad-url-blocks / bad-url-unblock, requiring the site-configuration permission).

Notes

  • Blocks live in lazysite/cache/bad-url-blocked.json; both the block store and the hit counters are size-bounded, so a scanning campaign cannot grow them without limit
  • Legitimate visitors are unaffected: ordinary page URLs are never counted, only probe-shaped ones