SSL-Zertifikat mit openssl prüfen

· 3 Min. Lesezeit

openssl ist auf jedem Linux und macOS vorhanden und zeigt genau das Zertifikat, das ein Server ausliefert, inklusive Kette und TLS-Version. Das ist nützlich, wenn der Browser eine Warnung zeigt, ein Kunde von IMAP-Fehlern berichtet oder ein Cronjob prüfen soll, wie lange ein Zertifikat noch gilt. Diese Anleitung zeigt die Befehle, die du dafür brauchst.

Die Verbindung: openssl s_client

s_client baut eine TLS-Verbindung auf und gibt aus, was der Server dabei präsentiert. -servername ist wichtig: Ohne SNI liefern viele Server das falsche Zertifikat, weil auf einer IP mehrere Domains liegen. Das abschließende </dev/null beendet die Sitzung, sonst wartet openssl auf Eingaben.

openssl s_client -connect beispiel.de:443 -servername beispiel.de </dev/null

In der Ausgabe stehen die Zertifikatskette (Certificate chain), das Zertifikat selbst in Base64, der Aussteller, die verwendete TLS-Version und am Ende "Verify return code". Steht dort 0 (ok), ist die Kette gegen die Stammzertifikate des Systems gültig. Andere Codes benennen das Problem: 10 für abgelaufen, 21 für ein nicht verifizierbares erstes Zertifikat (meist fehlt das Zwischenzertifikat), 18 für selbstsigniert.

Ablaufdatum, Aussteller und Namen auslesen

Die Ausgabe von s_client lässt sich an openssl x509 weiterreichen, das einzelne Felder ausgibt. So entstehen Einzeiler für Skripte und Cronjobs.

openssl s_client -connect beispiel.de:443 -servername beispiel.de </dev/null 2>/dev/null | openssl x509 -noout -dates
openssl s_client -connect beispiel.de:443 -servername beispiel.de </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject
openssl s_client -connect beispiel.de:443 -servername beispiel.de </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
openssl s_client -connect beispiel.de:443 -servername beispiel.de </dev/null 2>/dev/null | openssl x509 -noout -enddate -checkend 1209600

-dates zeigt notBefore und notAfter, -ext subjectAltName alle Hostnamen, für die das Zertifikat gilt. -checkend 1209600 prüft, ob das Zertifikat in den nächsten 14 Tagen (in Sekunden) abläuft, und liefert Exit-Code 1, wenn ja. Das ist die einfachste Form eines Ablauf-Checks in einem Shell-Skript.

Kette und Zwischenzertifikate

Ein Zertifikat, das auf dem Entwicklungsrechner funktioniert und auf Android-Geräten oder in Mailclients scheitert, hat fast immer eine unvollständige Kette: Der Server liefert nur sein eigenes Zertifikat, nicht das Zwischenzertifikat der CA. Desktop-Browser besorgen sich das fehlende Glied selbst, andere Clients nicht. -showcerts zeigt alle Zertifikate, die der Server tatsächlich sendet.

openssl s_client -connect beispiel.de:443 -servername beispiel.de -showcerts </dev/null 2>/dev/null | grep -E "^ [0-9]+ s:|^   i:"

Erwartet wird eine Kette aus zwei oder drei Einträgen: das Serverzertifikat (s: mit dem Hostnamen), dann das Zwischenzertifikat, dessen s: dem i: des Serverzertifikats entspricht. Erscheint nur ein Eintrag und der Verify-Code ist 21, fehlt das Zwischenzertifikat in der Serverkonfiguration: Bei nginx gehört die fullchain.pem in ssl_certificate, bei Apache seit 2.4.8 ebenfalls in SSLCertificateFile.

Mailserver: SMTP, IMAP und POP3

Mailserver-Zertifikate laufen unbemerkt ab, weil kein Browser warnt. Ports mit implizitem TLS (465, 993, 995) funktionieren wie 443. Ports mit STARTTLS (25, 587, 143, 110) beginnen unverschlüsselt und wechseln erst nach einem Kommando, deshalb braucht openssl die Option -starttls mit dem Protokoll.

openssl s_client -connect mail.beispiel.de:465 -servername mail.beispiel.de </dev/null
openssl s_client -connect mail.beispiel.de:993 -servername mail.beispiel.de </dev/null
openssl s_client -connect mail.beispiel.de:587 -starttls smtp -servername mail.beispiel.de </dev/null
openssl s_client -connect mail.beispiel.de:143 -starttls imap -servername mail.beispiel.de </dev/null
openssl s_client -connect mail.beispiel.de:25 -starttls smtp </dev/null

Der Hostname im Zertifikat muss zu dem passen, den die Mailclients verwenden. Ein Server, der als mail.beispiel.de konfiguriert ist, aber ein Zertifikat für server42.hoster.de ausliefert, erzeugt in Outlook und Apple Mail Warnungen bei jedem Start. Für den MX zählt der Hostname aus dem MX-Record, nicht die Domain.

TLS-Version und Cipher

Mit -tls1_2 oder -tls1_3 erzwingst du eine Version und siehst, ob der Server sie anbietet. Scheitert -tls1_3, spricht der Server noch kein TLS 1.3; gelingt -tls1 oder -tls1_1, sind veraltete Versionen noch aktiv, die abgeschaltet gehören.

openssl s_client -connect beispiel.de:443 -servername beispiel.de -tls1_3 </dev/null 2>&1 | grep -E "Protocol|Cipher"
openssl s_client -connect beispiel.de:443 -servername beispiel.de -tls1_1 </dev/null 2>&1 | grep -E "Protocol|error"

Zertifikatsdatei lokal prüfen

Vor dem Einspielen lässt sich eine Zertifikatsdatei ohne Server lesen, und ein häufiger Fehler beim Wechsel ist ein Zertifikat, das nicht zum privaten Schlüssel passt. Stimmen die beiden Modulus-Hashes überein, gehören Zertifikat und Schlüssel zusammen.

openssl x509 -in cert.pem -noout -text
openssl x509 -in cert.pem -noout -modulus | openssl md5
openssl rsa -in privkey.pem -noout -modulus | openssl md5

Von der Einzelprüfung zum Monitoring

Der -checkend-Einzeiler in einem Cronjob ist besser als nichts, prüft aber nur die Hosts, die jemand eingetragen hat, und schickt seine Mail an ein Postfach, das jemand lesen muss. Für viele Kundendomains samt Mailservern nimmt DomainWarn diese Arbeit ab: Es prüft jedes Zertifikat alle sechs Stunden, meldet 30 und 14 Tage vor Ablauf, erkennt Kettenfehler und passende Hostnamen und zeigt im Daily Digest, welche Zertifikate als Nächstes fällig sind.

Häufige Fragen

openssl meldet "unable to get local issuer certificate", das Zertifikat ist aber gültig.
Entweder fehlt das Zwischenzertifikat in der Serverkonfiguration (mit -showcerts prüfen), oder das System hat veraltete Stammzertifikate. Auf macOS hilft -CAfile mit einem aktuellen CA-Bundle, unter Linux das Paket ca-certificates aktualisieren.
Warum zeigt openssl ein anderes Zertifikat als der Browser?
Meist fehlt -servername. Ohne SNI liefert der Server sein Standardzertifikat, das zu einer anderen Domain auf derselben IP gehört.
Wie prüfe ich das Zertifikat auf einem Server, der noch nicht im DNS steht?
Mit -connect auf die IP-Adresse und -servername auf den künftigen Hostnamen: openssl s_client -connect 203.0.113.10:443 -servername beispiel.de. So testest du einen Umzug, bevor der A-Record umgestellt wird.
Jetzt prüfen

SSL-Zertifikat kostenlos prüfen: Ablaufdatum, Aussteller, Kette, Hostname und TLS-Version, auch Mailserver per Port. Erkennt abgelaufene und falsche Zertifikate.

DomainWarn prüft SPF, DKIM, DMARC, DNS und Zertifikate aller Kundendomains regelmäßig und meldet Änderungen, bevor Mails im Spam landen.

Diese Domain dauerhaft überwachen14 Tage kostenlos testen, keine Kreditkarte.

Weitere Anleitungen