Sync all scripts from website downloads — 352 scripts total

Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
This commit is contained in:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+558
View File
@@ -0,0 +1,558 @@
#!/bin/bash
################################################################################
# Script Name: add-fail2ban-nginx-hardening.sh
# Version: 1.0
# Description: Adds custom Fail2ban jails to block vulnerability scanners,
# script probes, and path enumeration attacks on nginx servers.
# Installs filters + jails and reloads Fail2ban.
#
# Author: Phil Connor
# Contact: contact@mylinux.work
# Website: https://mylinux.work
# License: MIT
#
# Usage:
# sudo ./add-fail2ban-nginx-hardening.sh
# sudo ./add-fail2ban-nginx-hardening.sh --logpath /var/log/nginx/access.log
# sudo ./add-fail2ban-nginx-hardening.sh --bantime 604800
# sudo ./add-fail2ban-nginx-hardening.sh --dry-run
#
################################################################################
set -euo pipefail
# ============================================================================
# DEFAULTS
# ============================================================================
readonly VERSION="1.0"
readonly SCRIPT_NAME="${0##*/}"
ACCESS_LOGPATH="auto"
ERROR_LOGPATH="auto"
BANTIME="86400"
DRY_RUN=false
SKIP_JAILS=""
ALLOW_EXTENSIONS=""
ALLOW_PATHS=""
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
log_step() { echo -e "${CYAN}[STEP]${NC} $*"; }
show_usage() {
cat <<EOF
Usage: sudo $SCRIPT_NAME [OPTIONS]
Adds nginx hardening jails to an existing Fail2ban installation.
Blocks vulnerability scanners, script probes, and path enumeration.
OPTIONS:
--logpath PATH Nginx access log path (default: auto-detect)
--error-logpath P Nginx error log path (default: auto-detect)
--bantime SECS Ban duration in seconds (default: 86400 / 24 hours)
--skip JAILS Comma-separated jails to skip
(noscript, pathscan, 4xx-flood)
--allow-ext LIST Comma-separated extensions to whitelist in noscript
(e.g., php,py for PHP/Python sites)
--allow-paths LIST Comma-separated paths to whitelist in pathscan
(e.g., wp-admin,phpmyadmin)
--dry-run Show what would be done without making changes
-h, --help Show this help message
JAILS INSTALLED:
nginx-noscript Blocks requests for .php, .asp, .jsp, .cgi, .exe
on servers that don't serve dynamic content.
*** SKIP this on PHP/ASP/Python sites or use
--allow-ext to whitelist your extensions ***
nginx-pathscan Blocks requests for sensitive paths like .env,
.git/, wp-admin, phpmyadmin, .aws/credentials.
*** Use --allow-paths to whitelist paths you
actually use (e.g., wp-admin on WordPress) ***
nginx-4xx-flood Bans IPs generating excessive 404/403 errors
(automated path enumeration / directory brute force).
Safe for all server types.
EXAMPLES:
# Static site — install all three jails
sudo $SCRIPT_NAME
# WordPress / PHP site — skip noscript, whitelist wp-admin
sudo $SCRIPT_NAME --skip noscript --allow-paths wp-admin,wp-login,xmlrpc
# PHP site with phpMyAdmin
sudo $SCRIPT_NAME --skip noscript --allow-paths phpmyadmin,pma
# Python/Django site
sudo $SCRIPT_NAME --allow-ext py --allow-paths admin
# Laravel site — only 4xx-flood and pathscan
sudo $SCRIPT_NAME --skip noscript --allow-paths api
# Ban for 7 days
sudo $SCRIPT_NAME --bantime 604800
# Preview without changes
sudo $SCRIPT_NAME --dry-run
EOF
exit 0
}
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--logpath) ACCESS_LOGPATH="$2"; shift 2 ;;
--error-logpath) ERROR_LOGPATH="$2"; shift 2 ;;
--bantime) BANTIME="$2"; shift 2 ;;
--skip) SKIP_JAILS="$2"; shift 2 ;;
--allow-ext) ALLOW_EXTENSIONS="$2"; shift 2 ;;
--allow-paths) ALLOW_PATHS="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
-h|--help) show_usage ;;
*) log_error "Unknown option: $1"; show_usage ;;
esac
done
}
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root (sudo)"
exit 1
fi
}
# ============================================================================
# CHECKS
# ============================================================================
check_fail2ban() {
if ! command -v fail2ban-client &>/dev/null; then
log_error "Fail2ban is not installed"
log_error "Install it first: https://mylinux.work/guides/fail2ban-setup/"
exit 1
fi
if ! systemctl is-active --quiet fail2ban; then
log_error "Fail2ban is not running"
exit 1
fi
log_info "Fail2ban is installed and running"
}
detect_logpaths() {
# Access log
if [[ "$ACCESS_LOGPATH" == "auto" ]]; then
if [[ -f /var/log/nginx/access.log ]]; then
ACCESS_LOGPATH="/var/log/nginx/access.log"
else
log_error "Could not find nginx access log. Use --logpath to specify."
exit 1
fi
elif [[ ! -f "$ACCESS_LOGPATH" ]]; then
log_error "Access log not found: $ACCESS_LOGPATH"
exit 1
fi
log_info "Access log: $ACCESS_LOGPATH"
# Error log
if [[ "$ERROR_LOGPATH" == "auto" ]]; then
if [[ -f /var/log/nginx/error.log ]]; then
ERROR_LOGPATH="/var/log/nginx/error.log"
else
ERROR_LOGPATH="$ACCESS_LOGPATH"
log_warn "Error log not found — using access log for all jails"
fi
fi
log_info "Error log: $ERROR_LOGPATH"
}
should_skip() {
local jail="$1"
[[ ",$SKIP_JAILS," == *",$jail,"* ]]
}
# Build extension regex excluding allowed extensions
build_extension_regex() {
local all_exts="php|asp|aspx|jsp|cgi|exe|pl"
if [[ -n "$ALLOW_EXTENSIONS" ]]; then
local result=""
IFS='|' read -ra EXT_ARRAY <<< "${all_exts}"
for ext in "${EXT_ARRAY[@]}"; do
if [[ ",$ALLOW_EXTENSIONS," != *",$ext,"* ]]; then
[[ -n "$result" ]] && result="${result}|"
result="${result}${ext}"
fi
done
if [[ -z "$result" ]]; then
log_warn "All extensions whitelisted — skipping nginx-noscript"
return 1
fi
echo "$result"
else
echo "$all_exts"
fi
return 0
}
# Build path ignore regex from allowed paths
build_path_ignoreregex() {
if [[ -z "$ALLOW_PATHS" ]]; then
echo ""
return
fi
local ignore_parts=""
IFS=',' read -ra PATH_ARRAY <<< "$ALLOW_PATHS"
for p in "${PATH_ARRAY[@]}"; do
p=$(echo "$p" | xargs | sed 's|^/||')
[[ -n "$ignore_parts" ]] && ignore_parts="${ignore_parts}|"
ignore_parts="${ignore_parts}/${p}"
done
echo "ignoreregex = ^<HOST> \\S+ \\S+ \\[.*\\] \"\\S+ [^\"]*($ignore_parts)[^\"]*HTTP"
}
# ============================================================================
# HELPER — write file with backup
# ============================================================================
write_config() {
local file="$1"
local label="$2"
if $DRY_RUN; then
log_info "[DRY RUN] Would create $file"
echo ""
cat
echo ""
return
fi
if [[ -f "$file" ]]; then
log_warn "$label already exists — backing up to ${file}.bak"
cp "$file" "${file}.bak"
fi
cat > "$file"
log_info "$label installed: $file"
}
# ============================================================================
# JAIL 1: nginx-noscript
# ============================================================================
install_noscript() {
if should_skip "noscript"; then
log_info "Skipping nginx-noscript (--skip)"
return
fi
local ext_regex
ext_regex=$(build_extension_regex) || return 0
log_step "Installing nginx-noscript filter and jail..."
if [[ -n "$ALLOW_EXTENSIONS" ]]; then
log_info "Whitelisted extensions: $ALLOW_EXTENSIONS"
fi
log_info "Blocking extensions: $ext_regex"
# Filter
generate_noscript_filter "$ext_regex" | write_config \
/etc/fail2ban/filter.d/nginx-noscript.conf \
"nginx-noscript filter"
# Jail
generate_noscript_jail | write_config \
/etc/fail2ban/jail.d/nginx-noscript.conf \
"nginx-noscript jail"
}
generate_noscript_filter() {
local ext_regex="$1"
cat <<EOF
# Fail2ban filter — nginx-noscript
# Blocks requests for dynamic script extensions that should never exist
# on a static site or any server not running those technologies.
# https://mylinux.work
#
# Blocked extensions: $ext_regex
[Definition]
# Match requests for script extensions in nginx access logs
failregex = ^<HOST> \S+ \S+ \[.*\] "(GET|POST|HEAD|PUT|DELETE|OPTIONS) [^"]*\.($ext_regex)(\?[^\"]*)? HTTP[^"]*" (400|403|404|444)
ignoreregex =
# Author: Phil Connor — https://mylinux.work
EOF
}
generate_noscript_jail() {
cat <<EOF
# Fail2ban jail — nginx-noscript
# Ban IPs requesting dynamic script files
# https://mylinux.work
[nginx-noscript]
enabled = true
port = http,https
filter = nginx-noscript
logpath = $ACCESS_LOGPATH
maxretry = 2
bantime = $BANTIME
findtime = 3600
# Author: Phil Connor — https://mylinux.work
EOF
}
# ============================================================================
# JAIL 2: nginx-pathscan
# ============================================================================
install_pathscan() {
if should_skip "pathscan"; then
log_info "Skipping nginx-pathscan (--skip)"
return
fi
log_step "Installing nginx-pathscan filter and jail..."
if [[ -n "$ALLOW_PATHS" ]]; then
log_info "Whitelisted paths: $ALLOW_PATHS"
fi
# Filter
local ignore_line
ignore_line=$(build_path_ignoreregex)
generate_pathscan_filter "$ignore_line" | write_config \
/etc/fail2ban/filter.d/nginx-pathscan.conf \
"nginx-pathscan filter"
# Jail
generate_pathscan_jail | write_config \
/etc/fail2ban/jail.d/nginx-pathscan.conf \
"nginx-pathscan jail"
}
generate_pathscan_filter() {
local ignore_line="$1"
[[ -z "$ignore_line" ]] && ignore_line="ignoreregex ="
cat <<EOF
# Fail2ban filter — nginx-pathscan
# Blocks requests for sensitive paths commonly targeted by vulnerability
# scanners, script kiddies, and automated exploit tools.
# https://mylinux.work
[Definition]
# Match requests for known sensitive/exploit paths
# Covers: environment files, version control, CMS admin panels,
# database tools, config files, cloud credentials
failregex = ^<HOST> \S+ \S+ \[.*\] "(GET|POST|HEAD) [^"]*(/\.env|/\.git|/\.svn|/\.hg|/\.htaccess|/\.htpasswd|/\.aws|/\.docker|/\.ssh|/\.kube|/\.config|/wp-admin|/wp-login|/wp-config|/wp-content/uploads|/wp-includes|/xmlrpc\.php|/administrator|/admin/config|/phpmyadmin|/pma|/myadmin|/dbadmin|/mysql|/phpinfo|/info\.php|/server-status|/server-info|/cgi-bin|/shell|/cmd|/command|/console|/config\.json|/config\.yml|/config\.yaml|/config\.xml|/database\.yml|/backup|/dump|/db\.sql|/\.sql|/api/v1/debug|/debug|/trace|/actuator|/swagger|/graphql|/solr|/elasticsearch|/_cat|/_cluster)[^"]*HTTP[^"]*" (400|403|404|444)
$ignore_line
# Author: Phil Connor — https://mylinux.work
EOF
}
generate_pathscan_jail() {
cat <<EOF
# Fail2ban jail — nginx-pathscan
# Ban IPs probing for sensitive paths
# https://mylinux.work
[nginx-pathscan]
enabled = true
port = http,https
filter = nginx-pathscan
logpath = $ACCESS_LOGPATH
maxretry = 1
bantime = $BANTIME
findtime = 3600
# Author: Phil Connor — https://mylinux.work
EOF
}
# ============================================================================
# JAIL 3: nginx-4xx-flood
# ============================================================================
install_4xx_flood() {
if should_skip "4xx-flood"; then
log_info "Skipping nginx-4xx-flood (--skip)"
return
fi
log_step "Installing nginx-4xx-flood filter and jail..."
# Filter
generate_4xx_filter | write_config \
/etc/fail2ban/filter.d/nginx-4xx-flood.conf \
"nginx-4xx-flood filter"
# Jail
generate_4xx_jail | write_config \
/etc/fail2ban/jail.d/nginx-4xx-flood.conf \
"nginx-4xx-flood jail"
}
generate_4xx_filter() {
cat <<'EOF'
# Fail2ban filter — nginx-4xx-flood
# Bans IPs generating excessive 4xx errors in a short period.
# Catches automated directory brute force and path enumeration.
# https://mylinux.work
[Definition]
# Match 400, 401, 403, 404, 405, 444 responses
failregex = ^<HOST> \S+ \S+ \[.*\] "\S+ \S+ \S+" (400|401|403|404|405|444)
ignoreregex =
# Author: Phil Connor — https://mylinux.work
EOF
}
generate_4xx_jail() {
cat <<EOF
# Fail2ban jail — nginx-4xx-flood
# Ban IPs with excessive 4xx errors (directory brute force)
# https://mylinux.work
[nginx-4xx-flood]
enabled = true
port = http,https
filter = nginx-4xx-flood
logpath = $ACCESS_LOGPATH
maxretry = 20
bantime = $BANTIME
findtime = 300
# Author: Phil Connor — https://mylinux.work
EOF
}
# ============================================================================
# RELOAD AND VERIFY
# ============================================================================
reload_fail2ban() {
log_step "Reloading Fail2ban..."
if $DRY_RUN; then
log_info "[DRY RUN] Would reload fail2ban"
return
fi
fail2ban-client reload
sleep 2
if systemctl is-active --quiet fail2ban; then
log_info "Fail2ban reloaded successfully"
else
log_error "Fail2ban failed to restart — check: journalctl -u fail2ban"
exit 1
fi
}
verify_jails() {
log_step "Verifying jails..."
if $DRY_RUN; then
log_info "[DRY RUN] Would verify jail status"
return
fi
local all_ok=true
echo ""
for jail in noscript pathscan 4xx-flood; do
if should_skip "$jail"; then
continue
fi
local full_jail="nginx-${jail}"
if fail2ban-client status "$full_jail" &>/dev/null; then
log_info "$full_jail is active"
else
log_error "$full_jail failed to start"
all_ok=false
fi
done
echo ""
if ! $all_ok; then
log_error "Some jails failed — debug with:"
log_error " fail2ban-client status"
log_error " fail2ban-regex $ACCESS_LOGPATH /etc/fail2ban/filter.d/<filter>.conf"
exit 1
fi
}
# ============================================================================
# MAIN
# ============================================================================
main() {
parse_args "$@"
echo ""
echo "============================================"
echo " Fail2ban Nginx Hardening v${VERSION}"
echo " https://mylinux.work"
echo "============================================"
echo ""
check_root
check_fail2ban
detect_logpaths
install_noscript
install_pathscan
install_4xx_flood
reload_fail2ban
verify_jails
local installed=0
should_skip "noscript" || installed=$((installed + 1))
should_skip "pathscan" || installed=$((installed + 1))
should_skip "4xx-flood" || installed=$((installed + 1))
echo "============================================"
echo " Setup Complete — ${installed} Jail(s) Installed"
echo "============================================"
echo ""
echo " Jails:"
should_skip "noscript" || echo " nginx-noscript Ban after 2 script requests (.php, .asp, etc.)"
should_skip "pathscan" || echo " nginx-pathscan Ban on first sensitive path probe (.env, .git, wp-admin)"
should_skip "4xx-flood" || echo " nginx-4xx-flood Ban after 20 errors in 5 minutes"
echo ""
echo " Log: $ACCESS_LOGPATH"
echo " Ban time: ${BANTIME}s ($(( BANTIME / 3600 ))h)"
echo ""
echo " Useful commands:"
echo " fail2ban-client status nginx-noscript"
echo " fail2ban-client status nginx-pathscan"
echo " fail2ban-client status nginx-4xx-flood"
echo " fail2ban-client set <jail> unbanip <IP>"
echo " fail2ban-regex $ACCESS_LOGPATH /etc/fail2ban/filter.d/nginx-pathscan.conf"
echo ""
}
main "$@"