Eigenen OCSP-Server erstellen mit OpenSSL

Erklärung

Ein OCSP-Server liefert bei verschlüsselten Verbindung dem aufrufenden Client eine Bestätigung ob das Zertifikat gültig ist. Wenn eine CA Zertifikate ausstellt kann sie über diesen Dienst dem Client mitteilen ob das Zertifikat noch gültig ist, wenn dieser eine verschlüsselte Webseite aufruft. Diese Variante ist eine Art der „Certificate-Transparency“. Der Vorgänger davon war die CRL-Liste. Hier wurde im Zertifikat ein HTTP-Pfad angegeben wo man diese Datei runterladen kann. Im OCSP-System ist die Aushandlung der Überprüfung
über ein „Nonce“ vorgesehen. Beide Systeme stehen meistens in einem Zertifikat:

Eintrag der CRL-Sperrliste

Diesen Eintrag findet man unter „CRL-Verteilungspunkte“ oder „Zertifizierungsstellen-Informations-Zugriff“

URI: http://crl.example.io/123.crl

Eintrag des OCSP-Server

Diesen Eintrag findet man unter „Zertifizierungsstelen-Informations-Zugriff“

OCSP: URI: http://ocsp.example.io/123

Ablauf der Abfrage

Der Client ruft eine Webseite per HTTPS auf. Die Gegenseite (Server) schickt dann sein öffentliches Zertifikat mit den oben genannten Angaben für den Eintrag des OCSP-Server und der CRL-Sperrliste. Bei diesen Drittadressen fragt der Client dann nach ob das Zertifikat gültig ist oder widerrufen wurde. Wurde es wieder widerrufen, dann verweigert der Client
den Seitenaufbau. Der Nachteil dieser Methode ist die Anfrage bei der Drittinstanz. Es gibt zwar eine Zeitregel in dem Protokoll, aber die Drittinstanz weiß über den Aufruf der Webseite bescheid. dafür gibt es für den Serverbetreiber die Funktion OCSP-Stapling. Mit dieser Variante fragt der Server der
Webseite die Gültigkeit ab und meldet sie an den Client mit. Dadurch ist dieser wieder anonym.

Der Crux bei Microsoft

Microsoft unterstützt laut seinen Angaben sowohl OCSP als auch CRL. Allerdings gibt es hier einen Bug. Nutzt man als OCSP Server OpenSSL, dann wird die Aushandlung per Nonce gemacht oder als Fallback eine Art CRL über OCSP. OpenSSL liefert aber in der CRL-Liste über OCSP nur ein expired Datum und kein Startdatum, dadurch gibt Windows in allen Versionen die Behauptung zurück, dass Zertifikat ist abgelaufen. Nur unter Windows-Server gibt es als Opt-IN die Funktion eine Nonce zu nutzen. Im Technet wird sich dazu wie folgt geäußert:

I believe you might misunderstand how Microsoft OCSP (and OCSP in general) works. Microsoft OCSP Responder is a server service that reads a CA’s CRL.
It uses this information as the authoritative source of revocation details for the CA. When a client queries the server (which is called the responder)
it provides an OCSP response to the client. If the OCSP Server/Responder can’t access the CRL, it can’t provide any revocation details to the client properly.
So in your case, your responder only has old/expired CRL information available to it. You will need to make sure your OCSP Responder can access the CRL.

If you are using a third party OCSP, you’d have to look into its configuration and details. One thing that could be going, just as a speculation, is your OCSP
Responder using NONCE for it’s responses? If so, Windows clients do not suppose NONCE.

Den kompletten Thread findet man unter folgender Quelle.

Leider entzieht sich mir die Sinnhaftigkeit dieser Aussage. Warum nutzt man nicht einfach den Modus der Nonce wie jeder Browser oder Andere bei OCSP? Der Vorteil wäre auch ein massiver Geschwindigkeitsgewinn mit OCSP-Stapling, da wir nicht immer eine Datei runterladen müssen. Witzigerweise kann Windows Server selber einen OCSP Server erstellen und der IIS OCSP Stapling. Nur die Clientversionen haben diesen Bug, was meines Erachtens keinen Sinn macht.

Einrichtung eines OCSP Servers mit OpenSSL

Mit OpenSSL kann man seine eigene CA bauen und einen OCSP Server betreiben. Grundkenntnisse in der Verwendung von OpenSSL sind hier hilfreich.

Root CA erstellen

Wir erstellen uns als erstes eine Root-CA. Als erstes brauchen wir einen Privatekey:

openssl genrsa -aes256 -out ca-key.pem 4096

und setzen darauf das Zertifikat auf mit:

openssl req -x509 -new -nodes -extensions v3_ca -key ca-key.pem -days 1460 -out ca-root.pem -sha384

Beim Request werden Standardfragen gestellt für zusätzliche Informationen. Im Feld „Common Name (e.g. server FQDN or YOUR name)“ trägt man den Name seiner CA. Anders als bei den Clientzertifikaten ist hier keine Domain notwendig.
Nun hat man seine Root CA.

Zertifikate für OCSP Server erstellen

Da der OCSP Server eine eigenes Zertifikat braucht, muss man hier den Vorgang noch mal wiederholen mit der Änderung, dass dieses Zertifikat verifiziert wird.

Wir führen in der Konfig von OpenSSL eine Erweiterung durch etc/ssl/openss.cnf. Es wird der neue Bereich:

[ v3_OCSP ]
#basicContraints = CA:FALSE
#keyusage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning

und ergänzt unter dem Punkt [usr_cert]

authorityInfoAccess = OCSP;URI:http://ocsp.example.io

Die beiden Punkte mit der # müssen im Bereich usr_cert aktiviert werden für die Erstellung der Zertifikate, da sonst eine Doppelnennung bemängelt wird.

Leider haben bei mir diese Ergänzungen nicht gewirkt, da die Konfig teilweise von usr/lib/openssl geladen wird, was aber nur ein Symlink ist auf die OpenSSL-Konfig. Also habe ich mir eine zweite Konfig für das OCSP-Serverzertifikat gebaut ocsp.cnf mit dem Inhalt:

# Subdomains
subjectAltName=DNS:ocsp.example.io,DNS:testsystem.example.io
# OCSP Server
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning
authorityInfoAccess = OCSP;URI:http://ocsp.example.io
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

Nun erstellen wir wieder einen privaten Schlüssel mit:

openssl genrsa -aes256 -out ocsp.key 4096

und erstellen eine CSR-Anfrage mit:

openssl req -sha384 -new -out ocsp.csr -key ocsp.key -extensions v3_OCSP

Jetzt wird das Zertifikat gegen die Root signiert:

openssl x509 -sha384 -req -in ocsp.csr -CA ca-root.pem -CAkey ca-key.pem -CAcreateserial -out ocsp.crt -days 1024 -sha384 -extfile ocsp.cnf -ocspid -ocsp_uri

Erstellung eines Client-Zertifikat

Nun können wir Zertifikate ausstellen für einen Client. Wir erzeugen wieder einen Private Key:

openssl genrsa -aes256 -out client.key 4096

und erstellen die CSR wieder:

openssl req -sha384 -new -out client.csr -key client.key

Jetzt brauchen wir eine weitere Konfig. Wir legen eine Datei mit an daten.cnf und geben der folgenden Inhalt:


# Gültigkeit eines Zertfikats für mehrere Subdomains
subjectAltName=DNS:test.example.io
# OCSP Server
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
authorityInfoAccess = OCSP;URI:http://ocsp.example.io
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# Weitere Einschr nkung der Nutzbarkeit des zu erstellenden Zertfikats
extendedKeyUsage=serverAuth,clientAuth

Jetzt wird wieder das Zertifikat signiert:

openssl x509 -sha384 -req -in client.csr -CA ca-root.pem -CAkey ca-key.pem -CAcreateserial -out client.crt -days 1024 -sha384 -extfile daten.cnf -ocspid -ocsp_uri

Datenbank des OCSP Server erstellen

Damit der OCSP Server gestartet werden kann, müssen wir eine Datenbank erstellen für diesen. Wichtig ist erstmal die Einrichtung der Pfade, da wir dies am Anfang noch nicht gemacht haben, sonst gibt es Fehlermeldungen:

In der Datei openssl.cnf ist dies die Rubrik:

[ CA_default ]

dir = ./ # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.

certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file

und erstellen 2 Dateien mit den Namen touch index.txt und touch index.txt.attr. Die letztere bekommt den Inhalt:

unique_subject = yes

Normalerweise erstellt OpenSSL beim ersten Mal diese Dateien selber. Manchmal müssen sie aber schon da sein und werden dann erneuert.

Wir tragen nun unsere Zertifikate ein mit:

openssl ca -valid /etc/ssl/private/client.crt
openssl ca -valid /etc/ssl/private/ocsp.crt

Schaut man sich nun die index.txt dann stehen dort folgende Daten:

V 210822092405Z D3A7DB29FCF2DAF7 unknown /C=AU/ST=Test/L=es/O=s/OU=s/CN=ocsp.example.io
V 210822093129Z D3A7DB29FCF2DAF8 unknown /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=test.example.io

– Das V gibt steht Status, für valid. Ist dort ein R, dann wurde das Zertifikat zurückgezogen
– Die Reihenfolge „210822093129Z“ ist das Ablaufdatum der Gültigkeit eines Zertifikates. Es wird Rückwärts gelesen. 2021.08.22 um 9:31:29 Zuluzeit läuft das Zertifikat ab (GMT+0)
– Die hexadezimale Zahlenfolge ist die Seriennummer des Zertifikates fortlaufend hier „D3A7DB29FCF2DAF7“

Gegebenfalls noch mal ein Update der Datenbank mit openssl ca -updatedb

OCSP Server starten

Nun starten wir den OCSP-Server mit

openssl ocsp -index /etc/ssl/index.txt -port 80 -rsigner /etc/ssl/private/ocsp.crt -rkey /etc/ssl/private/ocsp.key -CA /etc/ssl/cacert.pem -text -out log.txt

Die Ausgabe am Ende legt ein Log-Datei an, wo man die Anfragen sieht. Im produktiven Betrieb nicht unbedingt notwendig. Wir nehmen Port 80, da wir in der URI keinen speziellen Port angegeben haben. Beim Start wird das Passwort für den
Key abgefragt vom OCSP Zertifikat! Man sollte auch den Server nicht als Root laufen lassen. Am besten ist ein eigener Nutzer über eine Screeninstanz.

Prüfung der Funktion

Um die Funktion zu überprüfen öffnen wir eine zweite Instanz und schauen als erstes unser Zertifikat an mit:

openssl x509 -text -in client.crt

Hier muss folgendes drinne stehen:

X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:test.example.io
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment
Authority Information Access:
OCSP - URI:http://ocsp.example.io

X509v3 Subject Key Identifier:
75:36:F9:AF:02:18:E5:62:5F:1F:08:C3:FF:5B:D3:F3:05:08:34:F6
X509v3 Authority Key Identifier:
keyid:21:8B:BA:1C:23:EB:28:B2:74:EC:81:9E:83:3E:18:89:20:AB:3D:8 7

X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication

Man sieht hier sauber die Adresse des OCSP-Server.

Nun prüfen wir gegen den OCSP-Server. Da wir kein DNS haben, prüfen wir gegen 127.0.0.1 folgendermaßen:

openssl ocsp -CAfile /etc/ssl/cacert.pem -issuer /etc/ssl/cacert.pem -cert /etc/ssl/private/client.crt -url http://127.0.0.1 -resp_text

hier sind folgende Angaben wichtig am Ende:

Response verify OK
/etc/ssl/private/client.crt: good
This Update: Nov 2 11:56:19 2018 GMT

Dies teilt dem Client die Gültigkeit mit und wann ein Update gemacht wurde, also die Anfrage der Gültigkeit. Unser Zertifikat ist sauber. Die sieht man an der Angabe /etc/ssl/private/client.crt: good

Zertifikat über einen OCSP-Server zurückziehen

Um ein Zertifikat zurückzuziehen, muss man die Serverinstanz stoppen und folgendes eingegeben:

openssl ca -revoke /etc/ssl/private/client.crt

Gegebenfalls noch mal ein Update der Datenbank mit openssl ca -updatedb. Fragt man nun die index.txt ab, dann steht dort folgendes:

R 210822093129Z 181102120445Z D3A7DB29FCF2DAF8

Man sieht die Zeit des Rückruf noch dazu nun. Wir starten den OCSP-Server wieder mit:

openssl ocsp -index /etc/ssl/index.txt -port 80 -rsigner /etc/ssl/private/ocsp.crt -rkey /etc/ssl/private/ocsp.key -CA /etc/ssl/cacert.pem -text -out log.txt

und fragen das Zertifikat ab:

openssl ocsp -CAfile /etc/ssl/cacert.pem -issuer /etc/ssl/cacert.pem -cert /etc/ssl/private/client.crt -url http://127.0.0.1 -resp_text

Wir erhalten folgende Angabe am Ende der Abfrage:

Response verify OK
/etc/ssl/private/client.crt: revoked
This Update: Nov 2 12:09:15 2018 GMT
Revocation Time: Nov 2 12:04:45 2018 GMT

Das Zertifikat wurde widerrufen siehe /etc/ssl/private/client.crt: revoked. Auch ist die Angabe vorhanden wann. Man kann ein zurückgerufenes Zertifikat nicht wieder aktivieren, da die Seriennummer eindeutig sein muss. Es muss dann ein neues erstellt werden.

Fehler bei der Einrichtung

Sollten beim Ausführen der Befehle immer wieder Fehler auftauchen wie:

Can't open .//cacert.pem for reading, No such file or directory
140183270937856:error:02001002:system library:fopen:No such file or directory:../crypto/bio/bss_file.c:74:fopen('.//cacert.pem','r')
140183270937856:error:2006D080:BIO routines:BIO_new_file:no such file:../crypto/bio/bss_file.c:81:

stimmen die Pfadangaben nicht der Dateien. Gegebenfalls die Konfig anpassen für OpenSSL.

Der Fehler:

Error Loading extension section v3_OCSP
140186064438528:error:22097082:X509 V3 routines:do_ext_nconf:unknown extension name:../crypto/x509v3/v3_conf.c:78:
140186064438528:error:22098080:X509 V3 routines:X509V3_EXT_nconf:error in extension:../crypto/x509v3/v3_conf.c:47:name=basicContraints, value=CA:FALSE

Meldet das Vorhandensein von doppelten Argumenten in der OpenSSL durch das Laden der Erweiterung. Die hier genannten Argumente stehen schon im Bereich [ usr_cert ].

Zusatz

Die Anleitung wurde in einer Testumgebung erstellt und ist so nicht für den produktiven Betrieb geeignet! Möchte man diese im produktiven Betrieb nutzen, sollten Vorkehrungen getroffen zum Schutz der privaten Schlüssel und natürlich der CA.