PKI-Lab mit Root-CA und Teilnehmer-CA

Aus Xinux Wiki
Version vom 19. März 2026, 13:49 Uhr von Thomas.will (Diskussion | Beiträge) (→‎Zum Ziel kopieren)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

PKI mit Root-CA und Sub-CA (Beispiel it213)

In diesem Beispiel wird eine einfache PKI aufgebaut.

Der Trainer betreibt eine Root-CA.

Die Teilnehmer erzeugen eine Sub-CA, die von der Root-CA signiert wird.

Mit dieser Sub-CA werden anschließend Server-Zertifikate signiert.


Root-CA erstellen

Die Root-CA ist der Vertrauensanker der PKI und ist selbstsigniert.

  • openssl req -new -x509 -newkey rsa:4096 -nodes -keyout ca.key -out ca.crt -days 3650 -subj "/CN=Kit Root CA"

Das Zertifikat kann anschließend kontrolliert werden.

  • openssl x509 -in ca.crt -text -noout


Root-CA auf Clients installieren

Damit Clients den Zertifikaten vertrauen, muss die Root-CA im Trust-Store installiert werden.


Debian

Das Root-Zertifikat wird in den lokalen CA-Speicher kopiert.

  • cp ca.crt /usr/local/share/ca-certificates/

Der Trust-Store wird aktualisiert.

  • update-ca-certificates


Rocky / RHEL

Das Root-Zertifikat wird in den Anchor-Store kopiert.

  • cp ca.crt /etc/pki/ca-trust/source/anchors/

Der System Trust Store wird neu erzeugt.

  • update-ca-trust extract

Firefox / Chrome / Mozilla

Müssen getrennt importiert werden.

Sub-CA Request erzeugen (Beispiel it213)

Der Teilnehmer erzeugt einen privaten Schlüssel und eine Certificate Signing Request für seine CA.

  • mkdir intermediata-ca
  • cd intermediata-ca
  • openssl req -new -newkey rsa:4096 -nodes -keyout it213-ca.key -out it213-ca.csr -subj "/CN=it213 Lab CA"

Der Certificate Signing Request muss nun zur Zertifizierungsstelle

Sub-CA durch Root signieren

Die Root-CA signiert die Teilnehmer-CA. Dadurch entsteht die Zertifikatskette.

  • openssl x509 -req -in it213-ca.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out it213-ca.crt -days 1460 -extfile <(printf "basicConstraints=CA:TRUE\nkeyUsage=keyCertSign,cRLSign")

Das signierte CA-Zertifikat kann kontrolliert werden.

  • openssl x509 -in it213-ca.crt -text -noout

Die Zertifikate können nun hier runtergeladen werden


Hinweis zum privaten Schlüssel

Der private Schlüssel der CA wird nur zum Signieren von Zertifikaten benötigt.

Zum Prüfen der Zertifikatskette werden nur die öffentlichen Zertifikate verwendet.

Beispiel:

www.it213.int.crt
it213-ca.crt
ca.crt

Die Prüfung erfolgt über die Signaturen der Zertifikate.


Server-Schlüssel und CSR erzeugen

Variable setzen
  • CA=it213-ca
  • FQDN=www.it213.int

Der Teilnehmer erzeugt einen Schlüssel und eine CSR für seinen Server.

Erstellen
  • openssl req -new -newkey rsa:2048 -nodes -keyout $FQDN.key -out $FQDN.csr -subj "/CN=$FQDN"
Anzeigen
  • openssl req -in $FQDN.csr -text -noout

Server-Zertifikat signieren

Die Sub-CA signiert das Server-Zertifikat und fügt einen Subject Alternative Name hinzu.

Signieren
  • openssl x509 -req -in $FQDN.csr -CA $CA.crt -CAkey $CA.key -CAcreateserial -out $FQDN.crt -days 365 -extfile <(printf "subjectAltName=DNS:$FQDN")
Anzeigen
  • openssl x509 -in $FQDN.crt -text -noout

Fullchain erstellen

Damit Clients die Zertifikatskette aufbauen können, muss der Server die Intermediate-CA mitliefern.

Dazu wird eine Fullchain-Datei erstellt.

  • cat $FQDN.crt $CA.crt > $FQDN-fullchain.pem

Die Reihenfolge ist wichtig.

www.it213.int.crt
it213-ca.crt

Zum Ziel kopieren

  • scp $FQDN-fullchain.pem $FQDN.key kit@$FQDN:

Zertifikatskette prüfen

Die komplette Zertifikatskette kann mit OpenSSL überprüft werden.

  • openssl verify -CAfile ca.crt -untrusted it213-ca.crt www.it213.int.crt


PKI-Struktur

Kit Root CA
 └── it213-ca
      └── www.it213.int

Der Client kennt die Root-CA aus dem Trust-Store.

Der Server liefert beim TLS-Handshake das Server-Zertifikat und die Sub-CA.

Der Client kann damit die vollständige Zertifikatskette prüfen.

Troubleshooting: OpenSSL & PKI Fehler

Fehlermeldung / Symptom Mögliche Ursache Lösung
"Self-signed certificate in certificate chain" Der Client vertraut der Root-CA nicht oder die Root-CA wurde nicht im Trust-Store installiert. Prüfen, ob update-ca-certificates (Debian) oder update-ca-trust (Rocky) ausgeführt wurde. Browser ggf. neu starten.
"Depth lookup: unable to get local issuer certificate" Die Intermediate-CA (Sub-CA) fehlt in der Kette, die der Server ausliefert. Prüfen, ob die Datei fullchain.pem korrekt erstellt wurde (Reihenfolge!) und im Webserver (SSLCertificateFile / ssl_certificate) eingebunden ist.
"Certificate is not valid for 'xyz.int'" Der Subject Alternative Name (SAN) fehlt oder ist falsch geschrieben. Zertifikat prüfen mit: openssl x509 -in cert.crt -text -> Suche nach "X509v3 Subject Alternative Name".
"Verification error: certificate has expired" Systemzeit auf Server oder Client ist falsch (häufig bei VMs nach Suspend). Datum/Uhrzeit mit dem Befehl date prüfen und ggf. per NTP synchronisieren.
"Modulus mismatch" Der private Schlüssel passt kryptografisch nicht zum vorliegenden Zertifikat. Vergleichen der MD5-Hashes beider Dateien (siehe unten unter "Nützliche Befehle").
"CA:FALSE" bei der Sub-CA Die Sub-CA wurde ohne die Extension basicConstraints=CA:TRUE signiert. Die Sub-CA ist nicht berechtigt, weitere Zertifikate zu signieren. Sub-CA mit den richtigen Extensions neu erstellen.

Nützliche Prüfbefehle für die Administration

Modulus-Check (Passen Key und CRT zusammen?)

Um sicherzustellen, dass ein Zertifikat zu einem Private Key gehört, müssen die Modulus-Hashes identisch sein:

  • openssl x509 -noout -modulus -in www.it213.int.crt | openssl md5
  • openssl rsa -noout -modulus -in www.it213.int.key | openssl md5

TLS-Handshake live testen

Simuliert einen Verbindungsaufbau und zeigt die vom Server gesendete Zertifikatskette an:

  • openssl s_client -connect localhost:443 -showcerts

Zertifikatsinhalt schnell prüfen

  • openssl x509 -in fullchain.pem -text -noout


Python Webserver mit SSL/TLS

In dieser Anleitung wird ein einfacher HTTPS-Webserver mit Python erstellt, der statische Inhalte aus einem Verzeichnis ausliefert.

Als erstes müssen wir die fullchain.pem und den privaten Schlüssl zu Server bringen

  • scp fullchain.pem www.it213.int.key www:

Auf dem Webserver

  • ssh kit@www

Verzeichnis erstellen

Zuerst wird ein Arbeitsverzeichnis für die Webinhalte und das Server-Skript angelegt.

  • mkdir html

Keys anpassen

Die Zertifikatsdateien müssen in das Verzeichnis kopiert und für das Skript passend benannt werden.

  • cp fullchain.pem html/own.crt
  • cp www.it213.int.key html/own.key

Konfiguration

Das Python-Skript konfiguriert den Server so, dass er auf Port 8443 lauscht und die SSL-Verschlüsselung nutzt.

  • nano html/https.py
import http.server, ssl

server_address = ('0.0.0.0', 8443)
handler = http.server.SimpleHTTPRequestHandler
httpd = http.server.HTTPServer(server_address, handler)

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile="own.crt", keyfile="own.key")

httpd.socket = context.wrap_socket(httpd.socket, server_side=True)

print("HTTPS läuft auf https://0.0.0.0:8443")
httpd.serve_forever()

Statische Seite erstellen

Damit der Server eine Seite anzeigt, wird eine index.html im Verzeichnis erstellt.

  • nano html/index.html
<html>
<head>
<title>IT213 Testseite</title>
</head>
<body>
<h1>Erfolg!</h1>
<p>Der verschlüsselte Python-Webserver funktioniert und liefert diese Seite aus.</p>
</body>
</html>

Starten

Um den Server zu starten, wechselt man in das Verzeichnis und führt das Skript aus.

  • cd html
  • python3 https.py

Der Zugriff erfolgt im Browser über https://www.it213.int:8443.

Tests vom Client

Verschlüsselter Verbindungsaufbau
  • openssl s_client -host www.it213.int -port 8443
Welche Zertifikate werden angeboten?
  • nmap --script ssl-cert www.it213.int -p 8443
Welche SSL/TLS Versionen werden angeboten
  • nmap --script ssl-enum-ciphers www.it213.int -p 8443