Files
2026-10-25 20:46:32 +01:00

71 lines
2.2 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# npm-scanner – watch the NPM log directories for new hosts
# https://git.retronerd.at/schiwagoa/npm-scanner
#
# fail2ban resolves logpath globs only when a jail starts. A proxy host created later
# in NPM would therefore not be watched. This script reloads the jails as soon as a
# log file appears that no jail watches yet. Bans survive the reload.
#
# npm-newlog-watch.sh <dir> [<dir> …]
# NPM_SCANNER_JAILS="npm-scanner npm-wplogin" jails that read NPM logs
set -uo pipefail
JAILS=${NPM_SCANNER_JAILS:-npm-scanner}
SETTLE=${NEWLOG_SETTLE_SECONDS:-5}
log() { echo "[npm-newlog] $*"; }
[[ $# -gt 0 ]] || { log "no directories given"; exit 1; }
# Wait until the fail2ban server answers (max. 5 minutes).
for _ in $(seq 1 300); do
fail2ban-client ping >/dev/null 2>&1 && break
sleep 1
done
if ! fail2ban-client ping >/dev/null 2>&1; then
log "fail2ban does not answer – watcher stopped"
exit 1
fi
# Same mode the crazymax entrypoint chose (nft or legacy) is active by now.
chain=$(grep -m1 -oE 'chain=[A-Za-z0-9_-]+' /etc/fail2ban/jail.local | cut -d= -f2)
if [[ -n "$chain" ]] && ! iptables -n -L "$chain" >/dev/null 2>&1; then
log "WARNING: iptables chain $chain does not exist – bans will fail. Is Docker running on the host?"
fi
watched() {
local file=$1 jail
for jail in $JAILS; do
fail2ban-client get "$jail" logpath 2>/dev/null | grep -qF -- "$file" && return 0
done
return 1
}
declare -A tried=()
log "watching $* (jails: $JAILS)"
inotifywait -m -q -e create -e moved_to --format '%w%f' "$@" | while read -r file; do
case "${file##*/}" in
proxy-host-*_access.log|default-host_access.log|fallback_access.log|fallback_http_access.log) ;;
*) continue ;;
esac
[[ -n "${tried[$file]:-}" ]] && continue
# Give NPM time to finish writing the config, and debounce log rotation.
sleep "$SETTLE"
[[ -f "$file" ]] || continue
watched "$file" && continue
tried[$file]=1
for jail in $JAILS; do
# npm-wplogin only reads proxy-host logs.
[[ "$jail" == npm-wplogin && "${file##*/}" != proxy-host-* ]] && continue
if fail2ban-client reload "$jail" >/dev/null 2>&1; then
log "new log $file – $jail reloaded"
else
log "WARNING: reload of $jail failed for $file"
fi
done
done