Ich habe mein Heimnetzwerk in drei separate Bereiche unterteilt: ein Datencenter, eine DMZ (demilitarisierte Zone) und ein internes Client-Netzwerk. Um zu verhindern, dass meine Clients direkten Zugriff auf das Datencenter haben, habe ich einen NGINX-Reverse-Proxy in der DMZ eingerichtet. Dies ermöglicht sowohl Clients im Netzwerk als auch denen aus dem WAN (Wide Area Network) eine Verbindung. Zudem kann ich alle Websites mit einem Let’s Encrypt-Zertifikat absichern.
In den nächsten Tagen plane ich, einen Artikel über die Konfiguration von Apache2 als Reverse-Proxy mit ModSecurity und dem OWASP-Regelwerk zu veröffentlichen.
Inhaltsverzeichnis
Um NGINX und Certbot aus dem Standard-Repository auf einem Debian-basierten Betriebssystem zu installieren, kann der Paketmanager apt verwendet werden:
apt update apt install nginx certbot python3-certbot-nginx
Um ein Wildcard-Zertifikat für die Domain mit einer DNS-Challenge und Certbot anzufordern, müssen die folgenden Schritte ausgeführt werden:
certbot certonly --manual --preferred-challenges=dns --server https://acme-v02.api.letsencrypt.org/directory -d *.stangneth.com
Man muss den Anweisungen von Certbot zum Erstellen eines TXT-Eintrags in den DNS-Einstellungen folgen. Dies beinhaltet normalerweise das Einloggen in die Verwaltungskonsole des Domainanbieters und das Hinzufügen eines neuen TXT-Eintrags mit dem von Certbot bereitgestellten Wert.
Sobald der TXT-Eintrag hinzugefügt wurde, kehrt man zum Terminal zurück und drückt Enter, um den Zertifikatsanforderungsprozess fortzusetzen.
Certbot überprüft, ob der TXT-Eintrag korrekt hinzugefügt wurde und stellt bei Erfolg ein Wildcard-Zertifikat für die Domain aus.
Bitte beachten, dass dieser Prozess je nach Domainanbieter und den von ihm angebotenen DNS-Verwaltungstools variieren kann. Möglicherweise muss man die Dokumentation oder die Support-Ressourcen des Anbieters zu Rate ziehen.
Es wird gespeichert unter:
/etc/letsencrypt/live/stangneth.com/
Starten und aktivieren von NGINX:
systemctl start nginx systemctl enable nginx
Prüfen, ob NGINX ohne Fehler läuft:
systemctl status nginx
Um die Standardseite in NGINX zu deaktivieren, muss der symbolischen Link zur Standard-Site-Konfigurationsdatei aus dem Verzeichnis sites-enabled
entfernt werden. Dieses Verzeichnis wird von NGINX verwendet, um zu bestimmen, welche Site-Konfigurationen beim Start des Servers aktiviert und verwendet werden soll. Deaktivieren der Standardseite:
unlink /etc/nginx/sites-enabled/default
Wechseln in das sites-available
Verzeichnis und eine eigene Konfiguration anlegen:
cd /etc/nginx/sites-enabled/ vi 001-example.stangneth.com.conf
Um alle Standardanfragen auf Port 80 und Port 443 (HTTP und HTTPS) abzufangen und in NGINX einen 404-Fehler zurückzugeben, kann die folgende Konfiguration verwendet werden:
server { listen 80 default_server; server_name _; return 404; } server { listen 443 ssl default_server; server_name _; ssl_certificate /etc/letsencrypt/live/stangneth.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/stangneth.com/privkey.pem; return 404; }
Diese Konfiguration richtet zwei Server-Blöcke ein, einen für Port 80 und einen für Port 443. Die Direktive default_server
gibt an, dass diese Blöcke alle Standardanfragen abfangen sollen, die mit keinem anderen Server-Block übereinstimmen. Die Direktive return
wird verwendet, um dem Client einen 404-Fehler zurückzugeben.
Um alle HTTP-Anfragen auf HTTPS umzuleiten, kann die folgende Konfiguration verwendet werden:
server { listen 80; server_name example.stangneth.com; rewrite ^ https://$host$request_uri permanent; }
Schließlich können Sie den Teil für die erste Website auf Port 443 hinzufügen:
server { listen 443 ssl; server_name example.stangneth.com; ssl_certificate /etc/letsencrypt/live/stangneth.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/stangneth.com/privkey.pem; ssl_session_cache builtin:1000 shared:SSL:10m; ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; access_log /var/log/nginx/access.log; location / { allow 172.16.0.0/24; proxy_pass https://172.16.0.234; proxy_read_timeout 90; } }
Ich habe ein allow für einen bestimmten IP-Bereich hinzugefügt, sodass nicht jeder aus dem Internet auf die Seite zugreifen kann. Dies kann nützlich für Ressourcen sein, die ein offizielles Zertifikat von Let’s Encrypt haben sollen, aber nicht vom Internet aus erreichbar sein müssen. In meinem Fall handelt es sich um ein MediaWiki.
Die Konfiguration für die Webseite aktivieren:
ln -s /etc/nginx/sites-avaialable/001-example.stangneth.com.conf /etc/nginx/sites-enabled/001-example.stangneth.com.conf
NGINX neustarten und prüfen, ob die Webseite erreichbar ist (DNS prüfen!):
service nginx configtest systemctl restart nginx systemctl status nginx
Abhängigkeiten installieren:
apt install -y apt-utils autoconf automake build-essential git libcurl4-openssl-dev libgeoip-dev liblmdb-dev libpcre++-dev libtool libxml2-dev libyajl-dev pkgconf wget zlib1g-dev
Das Verzeichnis wechseln zu /usr/local/src
und das git repo klonen:
cd /usr/local/src git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
In das Verzeichnis wechseln und ModSecurity installieren:
cd ModSecurity/ git submodule init git submodule update ./build.sh ./configure make make install
Als nächstes den NGINX modsecurity connector von git klonen:
cd .. git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
Prüfen, welche NGINX Version installiert ist:
nginx -v
In diesem Fall 1.18.0. Den passenden Source Code herunterladen:
wget http://nginx.org/download/nginx-1.18.0.tar.gz tar zxvf nginx-1.18.0.tar.gz
Jetzt das modsecurity-nginx module kompilieren und es in das module Verzeichnis kopieren:
cd nginx-1.18.0/ ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx make modules cp /usr/local/src/nginx-1.18.0/objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
In der nginx.conf das Modul laden:
vi /etc/nginx/nginx.conf
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
NGINX neustarten und den Status prüfen:
systemctl restart nginx systemctl status nginx
Ein neues Verzeichnis für die ModSecurity Konfigurationsdateien anlegen:
mkdir /etc/nginx/modsec
Download der Standard modsecurity.conf-recommed vom SpiderLabs git repo:
wget -P /etc/nginx/modsec/ https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended mv /etc/nginx/modsec/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
Um sicher zu sein, das ModSecurity die unicode.mapping Datei finden kann kopiert man es nach /etc/nginx/modsec:
cp /usr/local/src/ModSecurity/unicode.mapping /etc/nginx/modsec/
In der modsecurity.conf den Eintrag SecRuleEngine ändern von „DetectionOnly“ zu „On“:
vi /etc/nginx/modsec/modsecurity.conf
Eine .conf Datei anlegen, wo es möglich ist bestimmte Webseitkonfigurationen anzupassen. In diesem Fall das ModSecurity laden:
vi /etc/nginx/modsec/main.conf
Include "/etc/nginx/modsec/modsecurity.conf"
Herunterladen des neusten OWASP coreruleset vom git repo:
cd /usr/local/src wget https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/v3.0.2.tar.gz tar -xzvf v3.0.2.tar.gz cd owasp-modsecurity-crs-3.0.2/
Kopieren der Beispiel Konfigurationsdatei:
cp crs-setup.conf.example crs-setup.conf
Öffnen der main.conf und laden des ruleset:
# OWASP CRS v3 rules Include /usr/local/src/owasp-modsecurity-crs-3.0.2/crs-setup.conf Include /usr/local/src/owasp-modsecurity-crs-3.0.2/rules/*.conf
Um ModSecurity für eine bestimmte Webseite zu aktivieren, passt man die .conf Datei an:
vi /etc/nginx/sites-available/001-example.stangneth.com.conf
server { listen 443 ssl; server_name example.stangneth.com; modsecurity on; modsecurity_rules_file /etc/nginx/modsec/main.conf; modsecurity_rules ' SecRuleRemoveById 949110 ';
Die SecRuleRemoveById section ist ein Beispiel. Es wird oft passieren das Webseiten nicht das komplette Ruleset benötigen/akzeptieren. Es wird zu false/postive Alarmen kommen.
Es ist möglich zu prüfen, welche Regel gezogen wurde:
tail -f /var/log/nginx/error.log
Ein output kann wie im folgenden Beispiel aussehen:
2022/12/27 14:38:39 [error] 1155#1155: *18 [client 172.16.0.123] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' ) [file "/usr/local/src/owasp-modsecurity-crs-3.0.2/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "44"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "172.16.0.233"] [uri "/api/v1/tickets/14"] [unique_id "167188911882.664343"] [ref ""], client: 172.16.0.123, server: example.stangneth.com, request: "PUT /api/v1/tickets/14?all=true HTTP/1.1", host: "example.stangneth.com", referrer: "https://example.stangneth.com/"
Hier war es notwendig die [id „949110“] von der Konfiguration DIESER einen Webseite zu entfernen. Bei anderen Webseiten muss das nicht der Fall sein.
Keine Kommentare zu NGINX als Reverse Proxy mit ModSecurity und OWASP Ruleset auf Debian