Nginx mit Modsecurity Rocky
Zur Navigation springen
Zur Suche springen
NGINX + ModSecurity v3 + OWASP CRS auf Rocky Linux (RHEL-kompatibel)
Voraussetzungen
- Rocky Linux 8/9 (SELinux enforcing möglich)
- Backend-Dienst (z. B. http://127.0.0.1:8080)
- TLS-Dateien: /etc/nginx/crt.pem, /etc/nginx/privkey.pem, optional /etc/nginx/ca.crt
Repos aktivieren
sudo dnf install -y epel-release # (Rocky 9) CRB einschalten, (Rocky 8) PowerTools: sudo dnf config-manager --set-enabled crb || sudo dnf config-manager --set-enabled powertools
Pakete installieren
sudo dnf install -y nginx modsecurity libmodsecurity nginx-mod-modsecurity git httpd-tools
Verzeichnisstruktur
sudo mkdir -p /etc/nginx/modsec
OWASP CRS 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
ModSecurity-Basisconfig
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
SecDebugLog /var/log/nginx/modsec_debug.log SecDebugLogLevel 3
SecTmpDir /tmp/ SecDataDir /tmp/
- Testregel (optional)
SecRule ARGS "@contains script" "id:9999,phase:1,deny,log,status:403,msg:'Test rule triggered'"
- OWASP CRS
Include /etc/nginx/modsec/coreruleset/crs-setup.conf Include /etc/nginx/modsec/coreruleset/rules/*.conf EOF
NGINX-ModSecurity-Snippet
sudo tee /etc/nginx/modsec/main.conf >/dev/null <<'EOF'
modsecurity on; modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf; EOF
NGINX Modul laden (wichtig auf Rocky)
- In /etc/nginx/nginx.conf ganz oben NACH "user" und VOR "events" einfügen:
load_module modules/ngx_http_modsecurity_module.so;
- Zusätzlich im http{}-Block das Logformat ergänzen (siehe "Logging")
Site-Config (/etc/nginx/conf.d/waf.conf)
sudo tee /etc/nginx/conf.d/waf.conf >/dev/null <<'EOF'
- HTTP → HTTPS Redirect
server {
listen 80; server_name _; return 301 https://$host$request_uri;
}
- HTTPS mit ModSecurity
server {
listen 443 ssl; server_name _;
ssl_certificate /etc/nginx/crt.pem; ssl_certificate_key /etc/nginx/privkey.pem; # Nur wenn mTLS gewünscht: # ssl_client_certificate /etc/nginx/ca.crt;
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
access_log /var/log/nginx/access.log waf_combined; error_log /var/log/nginx/error.log warn;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header Cache-Control "no-store, no-cache, must-revalidate";
error_page 403 /403.html;
location = /403.html {
root /usr/share/nginx/html;
internal;
}
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;
}
# Optional: Audit-Log im Browser (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
Fehlerseite (optional)
sudo tee /usr/share/nginx/html/403.html >/dev/null <<'EOF'
<html>
<head><title>403 Forbidden</title></head> <body>
Oops! Zugriff verweigert
Deine Anfrage wurde von der Web Application Firewall blockiert.
</body>
</html> EOF
Logging (in /etc/nginx/nginx.conf, im http{}-Block)
- In den http-Block einfügen:
log_format waf_combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'ModSecID=$request_id Host="$host" URI="$request_uri"';
Logdateien anlegen und Rechte
sudo touch /var/log/nginx/modsec_audit.log /var/log/nginx/modsec_debug.log sudo chown nginx:nginx /var/log/nginx/modsec_*.log sudo chmod 640 /var/log/nginx/modsec_*.log
Basic-Auth für /_waflog (optional)
sudo htpasswd -c /etc/nginx/.htpasswd admin
SELinux (empfohlen statt Abschalten)
- NGINX darf zu Backends verbinden:
sudo setsebool -P httpd_can_network_connect 1
- Wenn Logs unter /var/log/nginx bleiben, passt der Kontext. Bei eigenen Pfaden ggf.:
- sudo semanage fcontext -a -t httpd_log_t "/var/log/nginx(/.*)?"
- sudo restorecon -Rv /var/log/nginx
Firewall (Firewalld)
sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --reload
Start & Test
sudo nginx -t sudo systemctl enable --now nginx
- Test-Backend
python3 -m http.server 8080 &
- Abruf
curl -k https://localhost/
- Block-Test
curl -k "https://localhost/?param=<script>alert(1)</script>" -I
- Logs verfolgen
sudo tail -f /var/log/nginx/modsec_audit.log /var/log/nginx/error.log
Hinweise
- crs-setup.conf definiert Paranoia-Level, Variablen und Schwellenwerte.
- Regeln liegen unter /etc/nginx/modsec/coreruleset/rules/.
- Zugriff auf /_waflog erlaubt Audit-Log-Ansicht im Browser (Basic-Auth).
- ModSecurity greift nur, wenn include /etc/nginx/modsec/main.conf in der Server-Config enthalten ist.
- Auf Rocky MUSS das Modul explizit via load_module modules/ngx_http_modsecurity_module.so; in nginx.conf geladen werden.