Nginx mit Modsecurity Rocky

Aus Xinux Wiki
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/

  1. Testregel (optional)

SecRule ARGS "@contains script" "id:9999,phase:1,deny,log,status:403,msg:'Test rule triggered'"

  1. 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)

  1. In /etc/nginx/nginx.conf ganz oben NACH "user" und VOR "events" einfügen:
load_module modules/ngx_http_modsecurity_module.so;
  1. 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'
  1. HTTP → HTTPS Redirect

server {

   listen 80;
   server_name _;
   return 301 https://$host$request_uri;

}

  1. 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)

  1. 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)

  1. NGINX darf zu Backends verbinden:
sudo setsebool -P httpd_can_network_connect 1
  1. Wenn Logs unter /var/log/nginx bleiben, passt der Kontext. Bei eigenen Pfaden ggf.:
  2. sudo semanage fcontext -a -t httpd_log_t "/var/log/nginx(/.*)?"
  3. 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
  1. Test-Backend
python3 -m http.server 8080 &
  1. Abruf
curl -k https://localhost/
  1. Block-Test
curl -k "https://localhost/?param=<script>alert(1)</script>" -I
  1. 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.