Nginx mit Modsecurity und Blocklost Policy

Aus Xinux Wiki
Version vom 5. September 2025, 08:23 Uhr von Thomas.will (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „= NGINX mit ModSecurity und Blocklist-Policy = Diese Anleitung zeigt den Aufbau einer Web Application Firewall mit NGINX und ModSecurity v3 mit einer '''praxi…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

NGINX mit ModSecurity und Blocklist-Policy

Diese Anleitung zeigt den Aufbau einer Web Application Firewall mit NGINX und ModSecurity v3 mit einer praxistauglichen Blocklist-Strategie.

Voraussetzungen

  • Ubuntu 22.04 oder Debian 12
  • Funktionierendes Backend (z. B. http://127.0.0.1:8080)
  • TLS-Zertifikate (crt.pem, privkey.pem, ca.crt) aus interner CA

Installation

sudo apt update
sudo apt install nginx libmodsecurity3 libnginx-mod-http-modsecurity git apache2-utils -y

sudo mkdir -p /etc/nginx/modsec/custom-rules

OWASP Core Rule Set installieren

cd /etc/nginx/modsec
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf

Blocklist erstellen

sudo tee /etc/nginx/modsec/blocked_uris.txt > /dev/null <<EOF
/admin
/wp-admin
/administrator
/backup
/config
/database
/phpmyadmin
/mysql
/server-status
/.env
/.git
/wp-login.php
/login-bypass
EOF

ModSecurity konfigurieren

Datei: /etc/nginx/modsec/modsecurity.conf

sudo tee /etc/nginx/modsec/modsecurity.conf > /dev/null <<EOF
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off

SecAuditEngine RelevantOnly
SecAuditLog /var/log/nginx/modsec_audit.log
SecAuditLogParts ABIJDEFHZ

SecTmpDir /tmp/
SecDataDir /tmp/

# Zuerst CRS – wirkt auf ALLE Requests
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf

# Danach unsere Security Policy (Blocklist)
Include /etc/nginx/modsec/custom-rules/security-policy.conf
EOF

Security Policy (Blocklist)

Datei: /etc/nginx/modsec/custom-rules/security-policy.conf

sudo tee /etc/nginx/modsec/custom-rules/security-policy.conf > /dev/null <<EOF
# Security Policy: Blocklist + Default-Allow

# 1) KRITISCHE Pfade EXPLIZIT blockieren (Phase 1)
SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/blocked_uris.txt" \\
    "id:1999,phase:1,deny,status:403,log,msg:'Blocked path detected: %{MATCHED_VAR}'"

# 2) ALLES ANDERE ERLAUBEN (wird von CRS geprüft)
SecRule REQUEST_URI ".*" \\
    "id:2000,phase:1,pass,nolog"
EOF

NGINX-Snippet

Datei: /etc/nginx/modsec/main.conf

sudo tee /etc/nginx/modsec/main.conf > /dev/null <<EOF
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;
EOF

NGINX-Site konfigurieren

Datei: /etc/nginx/sites-available/default

sudo tee /etc/nginx/sites-available/default > /dev/null <<EOF
server {
    listen 80;
    server_name _;
    return 301 https://\$host\$request_uri;
}

server {
    listen 443 ssl;
    server_name _;

    ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    access_log /var/log/nginx/access.log waf_combined;
    error_log  /var/log/nginx/error.log warn;

    include /etc/nginx/modsec/main.conf;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    }

    # Audit-Log im Browser abrufbar (Basic-Auth)
    location /_waflog {
        alias /var/log/nginx/modsec_audit.log;
        types { }
        default_type text/plain;

        auth_basic "ModSecurity Auditlog";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}
EOF

Logging

# Log-Format ergänzen (/etc/nginx/nginx.conf im http{}-Block)
sudo sed -i '/http {/a\\tlog_format waf_combined '\''\$remote_addr - \$remote_user [\$time_local] '\''\\n\t\t\t\t\t'\''"\$request" \$status \$body_bytes_sent '\''\\n\t\t\t\t\t'\''"\$http_referer" "\$http_user_agent" '\''\\n\t\t\t\t\t'\''ModSecID=\$request_id Host="\$host" URI="\$request_uri"'\'';' /etc/nginx/nginx.conf

# Log-Dateien anlegen
sudo touch /var/log/nginx/modsec_audit.log
sudo chown www-data:adm /var/log/nginx/modsec_audit.log
sudo chmod 640 /var/log/nginx/modsec_audit.log

Fehlerseite

sudo tee /var/www/html/403.html > /dev/null <<EOF
<html>
 <head><title>403 Forbidden</title></head>
 <body>
 <h1>Zugriff verweigert</h1>
 <p>Deine Anfrage wurde von der Web Application Firewall blockiert.</p>
 </body>
</html>
EOF

Audit-Log im Browser

# Benutzerdatei anlegen
sudo htpasswd -c /etc/nginx/.htpasswd admin

Aktivierung

# Syntax prüfen
sudo nginx -t

# Nginx neu laden
sudo systemctl reload nginx

Testbeispiele

Methode URI Erwartung
GET / 200 OK
GET /admin 403 Forbidden
GET /wp-admin 403 Forbidden
POST /upload 200 OK (wenn erlaubt)

Audit-Log verfolgen

sudo tail -f /var/log/nginx/modsec_audit.log

Ergebnis

  • CRS schützt vor typischen Angriffen auf alle Requests
  • Blocklist blockiert explizit kritische Pfade
  • Default-Allow ermöglicht normale Seiten-Nutzung
  • Minimaler Wartungsaufwand durch Blocklist-Ansatz