Nginx Client Zertifikat: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „=Absicherung von Webdiensten mit 2FA: Zertifikat + Passwort= ==Voraussetzungen== ;Zertifikate * Eine eigene CA: ca.crt * Ein Server-Zertifikat: server.crt und…“)
 
 
(3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
=Absicherung von Webdiensten mit 2FA: Zertifikat + Passwort=
+
=Absicherung von Webdiensten mit 2FA: Zertifikat + Passwort (Nginx)=
 
+
==Einführung==
==Voraussetzungen==
+
* Zwei Faktoren: Besitz (Client-Zertifikat) und Wissen (Passwort).
;Zertifikate
+
* Der Server prüft das Client-Zertifikat gegen unsere CA (mTLS), danach folgt HTTP-Basic-Auth.
* Eine eigene CA: ca.crt
+
==Ausgangspunkt==
* Ein Server-Zertifikat: server.crt und server.key
+
* Bestehender Nginx-vHost secure.it2XX.int (Debian) mit fertigem Server-Zertifikat
* Ein Client-Zertifikat: client.crt und client.key
+
;Wenn vorhanden
 
+
*rm -v /var/www/secure/.htaccess
;Benutzer
+
*cat /etc/nginx/sites-available/secure.conf
* Ein Benutzerkonto für HTTP-Basic-Auth
+
<pre>
 
 
==Benutzer anlegen==
 
*htpasswd -c /etc/nginx/.htpasswd xinux
 
 
 
==NGINX-Konfiguration==
 
 
server {
 
server {
 
     listen 443 ssl;
 
     listen 443 ssl;
     server_name secure.lab.intern;
+
    listen [::]:443 ssl;
 
+
     server_name secure.it2XX.int;
     ssl_certificate /etc/nginx/ssl/server.crt;
+
    root /var/www/secure;
     ssl_certificate_key /etc/nginx/ssl/server.key;
+
    index index.html;
 
+
     ssl_certificate /etc/ssl/own.crt;
     ssl_client_certificate /etc/nginx/ssl/ca.crt;
+
    ssl_certificate_key /etc/ssl/own.key;
 +
    location / {
 +
        try_files $uri $uri/ =404;
 +
    }
 +
}
 +
</pre>
 +
==Auf dem CA-Host==
 +
===Client-Zertifikat erstellen===
 +
*cd ~/intermediate-ca
 +
<pre>
 +
#Variablen setzen
 +
CA=it2XX-ca
 +
USER_B=client
 +
#CSR erzeugen
 +
openssl req -new -newkey rsa:2048 -nodes -keyout $USER_B.key -out $USER_B.csr -subj "/CN=$USER_B"
 +
#Signieren
 +
openssl x509 -req -in $USER_B.csr -CA $CA.crt -CAkey $CA.key -CAcreateserial -out $USER_B.crt -days 365 -extfile <(printf "extendedKeyUsage=clientAuth")
 +
#PKCS12 für den Browser-Import bauen (Export-Passwort setzen)
 +
openssl pkcs12 -export -in $USER_B.crt -inkey $USER_B.key -certfile $CA.crt -out $USER_B.p12
 +
</pre>
 +
;$USER_B.p12 muss zum Client
 +
===Intermediate CA Fullchain===
 +
<pre>
 +
#Root-Zertifikat besorgen
 +
wget https://web.samogo.de/certs/ca.crt
 +
#CA-Fullchain erzeugen
 +
cat it2XX-ca.crt ca.crt > ca-fullchain.crt
 +
</pre>
 +
;ca-fullchain.crt muss zum Webserver
 +
==Benutzer für Basic-Auth anlegen==
 +
*htpasswd -c /etc/nginx/.htpasswd martha
 +
==Nginx-Konfiguration erweitern==
 +
*cat /etc/nginx/sites-available/secure.conf
 +
<pre>
 +
server {
 +
    listen 443 ssl;
 +
    listen [::]:443 ssl;
 +
    server_name secure.it2XX.int;
 +
    root /var/www/secure;
 +
    index index.html;
 +
    ssl_certificate /etc/ssl/own.crt;
 +
     ssl_certificate_key /etc/ssl/own.key;
 +
     ssl_client_certificate /etc/ssl/ca-fullchain.crt;
 
     ssl_verify_client on;
 
     ssl_verify_client on;
 
 
     ssl_protocols TLSv1.2 TLSv1.3;
 
     ssl_protocols TLSv1.2 TLSv1.3;
 
 
     location / {
 
     location / {
 
         auth_basic "Login mit Benutzername und Passwort";
 
         auth_basic "Login mit Benutzername und Passwort";
 
         auth_basic_user_file /etc/nginx/.htpasswd;
 
         auth_basic_user_file /etc/nginx/.htpasswd;
 
+
         try_files $uri $uri/ =404;
         root /var/www/html;
 
        index index.html;
 
 
     }
 
     }
 
}
 
}
 
+
</pre>
 +
;Config testen und neu laden
 +
*nginx -t
 +
*systemctl reload nginx
 
==Zertifikat im Firefox einbinden==
 
==Zertifikat im Firefox einbinden==
 
;Import
 
;Import
 
* Firefox → Einstellungen → Datenschutz & Sicherheit → Zertifikate anzeigen
 
* Firefox → Einstellungen → Datenschutz & Sicherheit → Zertifikate anzeigen
* Reiter "Ihre Zertifikate" → Importieren → client.p12
+
* Reiter "Ihre Zertifikate" → Importieren → client.p12 (Export-Passwort eingeben)
 
 
 
;Verwendung
 
;Verwendung
* Seite aufrufen: https://secure.lab.intern
+
* Seite aufrufen: https://secure.it2XX.int
 
* Firefox fragt nach Zertifikat → dann HTTP-Login
 
* Firefox fragt nach Zertifikat → dann HTTP-Login
 
 
==Test==
 
==Test==
 
;Kein Zertifikat
 
;Kein Zertifikat
* Fehler 400
+
* TLS-Handshake-Fehler (curl: alert certificate required, kein HTTP-Fehlercode)
 
 
 
;Falsches Passwort
 
;Falsches Passwort
 
* Fehler 401
 
* Fehler 401
 
 
;Zertifikat + Passwort korrekt
 
;Zertifikat + Passwort korrekt
 
* Zugriff erlaubt
 
* Zugriff erlaubt
 +
;Test mit curl
 +
*curl --cert client.crt --key client.key -u martha https://secure.it2XX.int
 +
==Optional: Nur bestimmten CN zulassen==
 +
* ssl_verify_client prüft nur die Signatur der CA – jedes von ihr ausgestellte Zertifikat wird akzeptiert.
 +
;Im location-Block ergänzen
 +
<pre>
 +
if ($ssl_client_s_dn !~ "CN=client") {
 +
    return 403;
 +
}
 +
</pre>
 +
;Testfall: gültiges Zertifikat, falscher CN
 +
* Fehler 403
 +
==Fazit==
 +
* mTLS plus Basic-Auth ergibt eine echte 2-Faktor-Absicherung: Besitz und Wissen.
 +
* ssl_client_certificate bestimmt, wessen Client-Zertifikate akzeptiert werden.

Aktuelle Version vom 12. Juni 2026, 12:40 Uhr

Absicherung von Webdiensten mit 2FA: Zertifikat + Passwort (Nginx)

Einführung

  • Zwei Faktoren: Besitz (Client-Zertifikat) und Wissen (Passwort).
  • Der Server prüft das Client-Zertifikat gegen unsere CA (mTLS), danach folgt HTTP-Basic-Auth.

Ausgangspunkt

  • Bestehender Nginx-vHost secure.it2XX.int (Debian) mit fertigem Server-Zertifikat
Wenn vorhanden
  • rm -v /var/www/secure/.htaccess
  • cat /etc/nginx/sites-available/secure.conf
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name secure.it2XX.int;
    root /var/www/secure;
    index index.html;
    ssl_certificate /etc/ssl/own.crt;
    ssl_certificate_key /etc/ssl/own.key;
    location / {
        try_files $uri $uri/ =404;
    }
}

Auf dem CA-Host

Client-Zertifikat erstellen

  • cd ~/intermediate-ca
#Variablen setzen
CA=it2XX-ca
USER_B=client
#CSR erzeugen
openssl req -new -newkey rsa:2048 -nodes -keyout $USER_B.key -out $USER_B.csr -subj "/CN=$USER_B"
#Signieren
openssl x509 -req -in $USER_B.csr -CA $CA.crt -CAkey $CA.key -CAcreateserial -out $USER_B.crt -days 365 -extfile <(printf "extendedKeyUsage=clientAuth")
#PKCS12 für den Browser-Import bauen (Export-Passwort setzen)
openssl pkcs12 -export -in $USER_B.crt -inkey $USER_B.key -certfile $CA.crt -out $USER_B.p12
$USER_B.p12 muss zum Client

Intermediate CA Fullchain

#Root-Zertifikat besorgen
wget https://web.samogo.de/certs/ca.crt
#CA-Fullchain erzeugen
cat it2XX-ca.crt ca.crt > ca-fullchain.crt
ca-fullchain.crt muss zum Webserver

Benutzer für Basic-Auth anlegen

  • htpasswd -c /etc/nginx/.htpasswd martha

Nginx-Konfiguration erweitern

  • cat /etc/nginx/sites-available/secure.conf
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name secure.it2XX.int;
    root /var/www/secure;
    index index.html;
    ssl_certificate /etc/ssl/own.crt;
    ssl_certificate_key /etc/ssl/own.key;
    ssl_client_certificate /etc/ssl/ca-fullchain.crt;
    ssl_verify_client on;
    ssl_protocols TLSv1.2 TLSv1.3;
    location / {
        auth_basic "Login mit Benutzername und Passwort";
        auth_basic_user_file /etc/nginx/.htpasswd;
        try_files $uri $uri/ =404;
    }
}
Config testen und neu laden
  • nginx -t
  • systemctl reload nginx

Zertifikat im Firefox einbinden

Import
  • Firefox → Einstellungen → Datenschutz & Sicherheit → Zertifikate anzeigen
  • Reiter "Ihre Zertifikate" → Importieren → client.p12 (Export-Passwort eingeben)
Verwendung

Test

Kein Zertifikat
  • TLS-Handshake-Fehler (curl: alert certificate required, kein HTTP-Fehlercode)
Falsches Passwort
  • Fehler 401
Zertifikat + Passwort korrekt
  • Zugriff erlaubt
Test mit curl

Optional: Nur bestimmten CN zulassen

  • ssl_verify_client prüft nur die Signatur der CA – jedes von ihr ausgestellte Zertifikat wird akzeptiert.
Im location-Block ergänzen
if ($ssl_client_s_dn !~ "CN=client") {
    return 403;
}
Testfall
gültiges Zertifikat, falscher CN
  • Fehler 403

Fazit

  • mTLS plus Basic-Auth ergibt eine echte 2-Faktor-Absicherung: Besitz und Wissen.
  • ssl_client_certificate bestimmt, wessen Client-Zertifikate akzeptiert werden.