Initial version: npm-scanner image, filters, entrypoint, watcher, testbed
- Image based on crazymax/fail2ban:1.1.1 with inotify-tools - Filters npm-scanner and npm-wplogin, tested with fail2ban-regex in the build - jail.local generated from .env, optional npm-wplogin and recidive - Watcher reloads the jails when NPM creates a new proxy host log - check command, docs, testbed for LXC Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
d7dcd9d6b1
29 files changed
+1163
No files matched your search
@@ -0,0 +1,22 @@
|
||||
# npm-scanner – fail2ban filter for Nginx Proxy Manager: scanners and probing
|
||||
# https://git.retronerd.at/schiwagoa/npm-scanner
|
||||
#
|
||||
# Rule 1 (proxy-host-*_access.log, NPM "proxy" format):
|
||||
# only 4xx answers to typical scanner paths
|
||||
# [25/Oct/2026:12:13:14 +0000] - 404 404 - GET https example.com "/.env" [Client 198.51.100.7] ...
|
||||
# Rule 2 (default-host / fallback log, combined format): status 444 or 400
|
||||
# (access by IP or unknown host name, broken requests)
|
||||
# Rule 3 (default-host / fallback log): scanner paths regardless of status (often 301 there)
|
||||
#
|
||||
# Deliberately NOT counted: plain 404 (Nextcloud/Matrix clients produce many legitimately)
|
||||
# and redirects on the default host without a scanner path (search engine crawlers).
|
||||
|
||||
[Definition]
|
||||
|
||||
_paths = (?:/\.env|/\.git/|/\.svn/|/\.aws/|/\.docker/|/\.ssh/|/\.s3cfg|/\.npmrc|/\.DS_Store|/\.vscode/|phpinfo|/info\.php|/_ignition/|/_profiler/|/wp-content/debug\.log|/phpmyadmin|/pma/|/cgi-bin/|/server-status|/actuator/|/vendor/phpunit|/boaform|/HNAP1|/secrets\.json|/credentials\.json|/docker-compose\.ya?ml|/\.gitlab-ci\.yml|/shell\.php|/eval-stdin\.php|\.(?:sql|bak|old|swp)(?:\.gz|\.zip)?(?=["?]))
|
||||
|
||||
failregex = - (?:\d{3}|-) 4\d\d - [A-Z]+ https? \S+ "[^"]*%(_paths)s[^"]*" \[Client <HOST>\]
|
||||
^<HOST> - \S+ .*?"[^"]*" (?:444|400)
|
||||
^<HOST> - \S+ .*?"[A-Z]+ [^"]*%(_paths)s[^"]*" \d{3}
|
||||
|
||||
ignoreregex =
|
||||
@@ -0,0 +1,11 @@
|
||||
# npm-wplogin – fail2ban filter for Nginx Proxy Manager: WordPress login brute force
|
||||
# https://git.retronerd.at/schiwagoa/npm-scanner
|
||||
#
|
||||
# Counts POST requests to wp-login.php and xmlrpc.php on every host behind this NPM.
|
||||
# [25/Oct/2026:12:13:14 +0000] - 200 200 - POST https blog.example.com "/wp-login.php" [Client 198.51.100.7] ...
|
||||
|
||||
[Definition]
|
||||
|
||||
failregex = - (?:\d{3}|-) (?:200|302|403|404) - POST https? \S+ "/(?:wp-login\.php|xmlrpc\.php)[^"]*" \[Client <HOST>\]
|
||||
|
||||
ignoreregex =
|
||||
@@ -0,0 +1,6 @@
|
||||
# Generated by npm-scanner at container start – do not edit.
|
||||
# Own additions and overrides: ./data/jail.d/*.local (read after this file).
|
||||
|
||||
[DEFAULT]
|
||||
ignoreip = 127.0.0.1/8 ::1 @WHITELIST@
|
||||
backend = pyinotify
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
# Scanners and probing. Ban in @F2B_CHAIN@ on all ports
|
||||
# (Docker routes published ports past INPUT).
|
||||
[npm-scanner]
|
||||
enabled = true
|
||||
filter = npm-scanner
|
||||
logpath = @LOGPATH_SCANNER@
|
||||
maxretry = @SCANNER_MAXRETRY@
|
||||
findtime = @SCANNER_FINDTIME@
|
||||
bantime = @SCANNER_BANTIME@
|
||||
bantime.increment = true
|
||||
bantime.maxtime = @SCANNER_MAXTIME@
|
||||
action = iptables-allports[name=npm-scan, chain=@F2B_CHAIN@, protocol=all]
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
# WordPress login brute force (POST wp-login.php / xmlrpc.php).
|
||||
[npm-wplogin]
|
||||
enabled = true
|
||||
filter = npm-wplogin
|
||||
logpath = @LOGPATH_PROXY@
|
||||
maxretry = @WPLOGIN_MAXRETRY@
|
||||
findtime = @WPLOGIN_FINDTIME@
|
||||
bantime = @WPLOGIN_BANTIME@
|
||||
bantime.increment = true
|
||||
bantime.maxtime = @WPLOGIN_MAXTIME@
|
||||
action = iptables-allports[name=npm-wp, chain=@F2B_CHAIN@, protocol=all]
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
# Repeat offenders across all jails: blocked in INPUT and @F2B_CHAIN@.
|
||||
[recidive]
|
||||
enabled = true
|
||||
logpath = @F2B_LOGFILE@
|
||||
findtime = @RECIDIVE_FINDTIME@
|
||||
maxretry = @RECIDIVE_MAXRETRY@
|
||||
bantime = @RECIDIVE_BANTIME@
|
||||
action = iptables-allports[name=recidive-input, chain=INPUT, protocol=all]
|
||||
iptables-allports[name=recidive-docker, chain=@F2B_CHAIN@, protocol=all]
|
||||
Reference in new issue
Block a user