diff --git a/scripts/fail2ban/etc-prs.conf b/scripts/fail2ban/etc-prs.conf new file mode 100644 index 0000000..6dd800d --- /dev/null +++ b/scripts/fail2ban/etc-prs.conf @@ -0,0 +1,52 @@ +# /etc/fail2ban/jail.d/etc-prs.conf +# Fail2ban configuration for ETC PRS server +# +# Install: +# sudo cp scripts/fail2ban/nginx-scan.conf /etc/fail2ban/filter.d/nginx-scan.conf +# sudo cp scripts/fail2ban/etc-prs.conf /etc/fail2ban/jail.d/etc-prs.conf +# sudo systemctl restart fail2ban +# sudo fail2ban-client status nginx-scan + +[DEFAULT] +# Ban IPs using UFW (already configured on this server) +banaction = ufw + +[nginx-scan] +enabled = true +port = http,https +filter = nginx-scan +logpath = /var/log/nginx/access.log + +# Ban if 20 errors in 60 seconds +maxretry = 20 +findtime = 60 + +# Ban for 1 hour +bantime = 3600 + +[nginx-badbots] +enabled = true +port = http,https +filter = nginx-badbots +logpath = /var/log/nginx/access.log +maxretry = 2 +findtime = 86400 +bantime = 86400 + +[nginx-noscript] +enabled = true +port = http,https +filter = nginx-noscript +logpath = /var/log/nginx/access.log +maxretry = 6 +findtime = 60 +bantime = 3600 + +[sshd] +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 5 +findtime = 60 +bantime = 3600 diff --git a/scripts/fail2ban/install.sh b/scripts/fail2ban/install.sh new file mode 100644 index 0000000..7f3cfdb --- /dev/null +++ b/scripts/fail2ban/install.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# ============================================================================= +# ETC PRS — Install & configure fail2ban +# Usage: sudo bash scripts/fail2ban/install.sh +# ============================================================================= + +set -euo pipefail + +RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m' +info() { echo -e "${CYAN}▸ $*${RESET}"; } +success() { echo -e "${GREEN}✓ $*${RESET}"; } +error() { echo -e "${RED}✗ $*${RESET}"; exit 1; } + +[[ $EUID -ne 0 ]] && error "Run as root: sudo bash scripts/fail2ban/install.sh" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# ── Install fail2ban ────────────────────────────────────────────────────────── +info "Installing fail2ban…" +apt-get install -y -qq fail2ban + +# ── Copy filter and jail config ─────────────────────────────────────────────── +info "Installing filter: nginx-scan…" +cp "$SCRIPT_DIR/nginx-scan.conf" /etc/fail2ban/filter.d/nginx-scan.conf + +info "Installing jail config…" +cp "$SCRIPT_DIR/etc-prs.conf" /etc/fail2ban/jail.d/etc-prs.conf + +# ── Ensure Nginx is logging in combined format ──────────────────────────────── +# fail2ban reads /var/log/nginx/access.log — verify it exists +if [[ ! -f /var/log/nginx/access.log ]]; then + error "Nginx access log not found at /var/log/nginx/access.log — is Nginx running?" +fi +success "Nginx access log found" + +# ── Enable and restart fail2ban ─────────────────────────────────────────────── +info "Enabling fail2ban service…" +systemctl enable fail2ban +systemctl restart fail2ban + +sleep 2 + +# ── Verify ──────────────────────────────────────────────────────────────────── +success "fail2ban installed and running" +echo "" +echo -e "${BOLD}Active jails:${RESET}" +fail2ban-client status + +echo "" +echo -e "${BOLD}Useful commands:${RESET}" +echo -e " ${CYAN}sudo fail2ban-client status nginx-scan${RESET} — show banned IPs" +echo -e " ${CYAN}sudo fail2ban-client set nginx-scan unbanip ${RESET} — unban an IP" +echo -e " ${CYAN}sudo tail -f /var/log/fail2ban.log${RESET} — live ban log" +echo "" diff --git a/scripts/fail2ban/nginx-scan.conf b/scripts/fail2ban/nginx-scan.conf new file mode 100644 index 0000000..978c39c --- /dev/null +++ b/scripts/fail2ban/nginx-scan.conf @@ -0,0 +1,8 @@ +[Definition] +# Match lines from nginx access log with 4xx/5xx responses +# Nginx combined log format: +# 1.2.3.4 - - [18/Mar/2026:09:45:00 +0000] "GET /backend/config/default.yml HTTP/1.1" 404 ... +failregex = ^ .+ "(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH) .+ HTTP/\d\.\d" 40[0-9] .+$ + ^ .+ "(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH) .+ HTTP/\d\.\d" 5[0-9]{2} .+$ + +ignoreregex = diff --git a/src/routes/admin/+page.svelte b/src/routes/admin/+page.svelte index 3b28a00..07ed56d 100644 --- a/src/routes/admin/+page.svelte +++ b/src/routes/admin/+page.svelte @@ -644,4 +644,4 @@ {/each} {/if} - \ No newline at end of file +