Verwenden Sie openssl, um das Zertifikat von einem Server abzurufen

353

Ich versuche, das Zertifikat eines Remote-Servers abzurufen, das ich dann zu meinem Keystore hinzufügen und in meiner Java-Anwendung verwenden kann.

Ein älterer Entwickler (der in den Ferien ist :() hat mir mitgeteilt, dass ich das ausführen kann:

openssl s_client -connect host.host:9999

Um ein Rohzertifikat zu erhalten, das ich dann kopieren und exportieren kann. Ich erhalte folgende Ausgabe:

depth=1 /C=NZ/ST=Test State or Province/O=Organization Name/OU=Organizational Unit Name/CN=Test CA
verify error:num=19:self signed certificate in certificate chain
verify return:0
23177:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1086:SSL alert number 40
23177:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:188:

Ich habe es auch mit dieser Option versucht

-showcerts 

und dieser (läuft auf Debian wohlgemerkt)

-CApath /etc/ssl/certs/ 

Aber bekomme den gleichen Fehler.

Diese Quelle sagt, dass ich dieses CApath-Flag verwenden kann, aber es scheint nicht zu helfen. Ich habe mehrere Pfade ohne Erfolg ausprobiert.

Bitte lassen Sie mich wissen, wo ich falsch liege.

böse Pastete
quelle

Antworten:

462

Mit SNI

Wenn der Remote-Server SNI verwendet (dh mehrere SSL-Hosts unter einer einzigen IP-Adresse gemeinsam nutzen), müssen Sie den richtigen Hostnamen senden, um das richtige Zertifikat zu erhalten.

openssl s_client -showcerts -servername www.example.com -connect www.example.com:443 </dev/null

Ohne SNI

Wenn der Remote-Server kein SNI verwendet, können Sie folgende -servernameParameter überspringen :

openssl s_client -showcerts -connect www.example.com:443 </dev/null


Um die vollständigen Details des Zertifikats einer Site anzuzeigen, können Sie auch diese Befehlskette verwenden:

$ echo | \
    openssl s_client -servername www.example.com -connect www.example.com:443 2>/dev/null | \
    openssl x509 -text
Ari Maniatis
quelle
3
Hmm. Ich erhalte immer noch den gleichen Fehler, wenn ich diesen Befehl versuche. Ich habe festgestellt, dass meine Openssl-Version 'OpenSSL 0.9.8g 19 Oct 2007' ist. Hast du eine Idee?
böse Pastete
39
Nützlich: echo "" | openssl s_client -connect server:port -prexit 2>/dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' stackoverflow.com/a/12918442/843000
mbrownnyc
16
Alternatives nützliches Skript von madboa.com :echo | openssl s_client -connect server:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
rmeakins
9
Um diesen etwas prägnanter zu machen, können Sie die ersetzen sedmit openssl x509und lesen es eine Unterschale mit:openssl x509 -in <(openssl s_client -connect server:port -prexit 2>/dev/null)
Gabe Martin-Dempesy
27
Auchecho | openssl s_client -connect google.com:443 2>/dev/null | openssl x509
MattSizzle
68

Obwohl ich der Antwort von Ari zustimme (und sie positiv bewertet habe :), musste ich einen zusätzlichen Schritt ausführen, damit sie unter Windows mit Java funktioniert (wo sie bereitgestellt werden musste):

openssl s_client -showcerts -connect www.example.com:443 < /dev/null | openssl x509 -outform DER > derp.der

Vor dem Hinzufügen der openssl x509 -outform DERKonvertierung wurde von keytool unter Windows eine Fehlermeldung angezeigt, in der über das Format des Zertifikats geklagt wurde. Das Importieren der .der-Datei hat einwandfrei funktioniert.

David Jaquay
quelle
Seltsam. Ich verwende seit Java 6 PEM-Zertifikate mit Keytool unter Windows und hatte nie ein Problem.
imgx64
39

Es stellt sich heraus, dass hier mehr Komplexität besteht: Ich musste viel mehr Details bereitstellen, um dies ins Rollen zu bringen. Ich denke, es hat etwas mit der Tatsache zu tun, dass es sich um eine Verbindung handelt, die eine Clientauthentifizierung benötigt, und der Hankshake benötigte weitere Informationen, um mit dem Stadium fortzufahren, in dem die Zertifikate ausgegeben wurden.

Hier ist mein Arbeitsbefehl:

openssl s_client -connect host:port -key our_private_key.pem -showcerts \
                 -cert our_server-signed_cert.pem

Hoffentlich ist dies ein Anstoß in die richtige Richtung für alle, die mehr Informationen brauchen könnten.

böse Pastete
quelle
6
Es tut mir leid, aber Ihre Antwort macht nicht viel Sinn. Sie mussten das Zertifikat an den Server übergeben, um das Zertifikat zu erhalten?
Ari Maniatis
2
Ja. Client-Authentifizierung AFAIK.
böse Pastete
11
Es stellt sich heraus, dass '-prexit' auch diese Daten zurückgibt. Z.B; openssl s_client -connect host: port -prexit
Robert
39

Ein Einzeiler zum Extrahieren des Zertifikats von einem Remote-Server im PEM-Format, diesmal mit sed:

openssl s_client -connect www.google.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
André Fernandes
quelle
2
Dieser ist fast perfekt, um das Zertifikat zu extrahieren. -servernameIch habe nur die Option verpasst und weiß nicht warum, aber ich musste ihn verwenden, um das vollständige Zertifikat zu erhalten.
Karl.S
-servername ist für die Angabe des Servernamens (SNI) erforderlich. Die Websuche kann den Rest erweitern.
Sam Gleske
32

Die einfachste Befehlszeile hierfür, die die PEM-Ausgabe zum Hinzufügen zum Keystore sowie eine von Menschen lesbare Ausgabe enthält und auch SNI unterstützt, was wichtig ist, wenn Sie mit einem HTTP-Server arbeiten, ist:

openssl s_client -servername example.com -connect example.com:443 \
    </dev/null 2>/dev/null | openssl x509 -text

Die Option -servername dient zum Aktivieren der SNI-Unterstützung, und der openssl x509-Text druckt das Zertifikat in einem für Menschen lesbaren Format.

Florian
quelle
Sie können Ihrem -servername Ihre Subdomain hinzufügen, z. B. ws.example.com anstelle von example.com (wenden Sie dies auch auf den Parameter -connect an).
Russellhoff
24

Um das Zertifikat des Remote - Servers erhalten Sie verwenden können opensslWerkzeug und Sie können es zwischen finden BEGIN CERTIFICATEund END CERTIFICATEwelche müssen Sie kopieren und in Ihre Zertifikatsdatei (CRT).

Hier ist der Befehl, der dies demonstriert:

ex +'/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq > file.crt

Um alle Zertifikate aus der Kette zurückzugeben, fügen Sie einfach g(global) wie folgt hinzu :

ex +'g/BEGIN CERTIFICATE/,/END CERTIFICATE/p' <(echo | openssl s_client -showcerts -connect example.com:443) -scq

Dann können Sie einfach Ihre Zertifikatdatei ( file.crt) in Ihren Schlüsselbund importieren und vertrauenswürdig machen, sodass sich Java nicht beschweren sollte.

Unter OS X können Sie auf die Datei doppelklicken oder Ihren Schlüsselbundzugriff per Drag & Drop verschieben, damit er in Login / Zertifikaten angezeigt wird. Doppelklicken Sie dann auf das importierte Zertifikat und machen Sie es für SSL immer vertrauenswürdig .

Unter CentOS 5 können Sie sie an eine /etc/pki/tls/certs/ca-bundle.crtDatei anhängen (und ausführen sudo update-ca-trust force-enable:) oder in CentOS 6 in eine Datei kopieren /etc/pki/ca-trust/source/anchors/und ausführen sudo update-ca-trust extract.

Kopieren Sie sie in Ubuntu in /usr/local/share/ca-certificatesund führen Sie sie aus sudo update-ca-certificates.

Kenorb
quelle
12
HOST=gmail-pop.l.google.com
PORT=995

openssl s_client -servername $HOST -connect $HOST:$PORT < /dev/null 2>/dev/null | openssl x509 -outform pem
akond
quelle
6

So drucken Sie nur die Zertifikatkette und nicht das Zertifikat des Servers:

# MYHOST=myhost.com
# MYPORT=443
# openssl s_client -connect ${MYHOST}:${MYPORT} -showcerts 2>/dev/null </dev/null | awk '/^.*'"${MYHOST}"'/,/-----END CERTIFICATE-----/{next;}/-----BEGIN/,/-----END CERTIFICATE-----/{print}'

So aktualisieren Sie die CA-Vertrauenswürdigkeit unter CentOS / RHEL 6/7:

# update-ca-trust enable
# openssl s_client -connect ${MYHOST}:${MYPORT} -showcerts 2>/dev/null </dev/null | awk '/^.*'"${MYHOST}"'/,/-----END CERTIFICATE-----/{next;}/-----BEGIN/,/-----END CERTIFICATE-----/{print}' >/etc/pki/ca-trust/source/anchors/myca.cert
# update-ca-trust extract

unter CentOS / RHEL 5:

# openssl s_client -connect ${MYHOST}:${MYPORT} -showcerts 2>/dev/null </dev/null | awk '/^.*'"${MYHOST}"'/,/-----END CERTIFICATE-----/{next;}/-----BEGIN/,/-----END CERTIFICATE-----/{print}' >>/etc/pki/tls/certs/ca-bundle.crt
Mathieu CARBONNEAUX
quelle
Genau das, was ich auf CentOS7 brauchte. Vielen Dank!
Arthur Hebert
5

Sie können das Server-Stammzertifikat mit dem nächsten Bash-Skript abrufen und speichern:

CERTS=$(echo -n | openssl s_client -connect $HOST_NAME:$PORT -showcerts | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p')
echo "$CERTS" | awk -v RS="-----BEGIN CERTIFICATE-----" 'NR > 1 { printf RS $0 > "'$SERVER_ROOT_CERTIFICATE'"; close("'$SERVER_ROOT_CERTIFICATE'") }'

Überschreiben Sie einfach die erforderlichen Variablen.

Andrei Aleksandrov
quelle
4

Wenn Ihr Server ein E-Mail-Server ist (MS Exchange oder Zimbra), müssen Sie möglicherweise die starttlsund smtp-Flaggen hinzufügen :

openssl s_client -starttls smtp -connect HOST_EMAIL:SECURE_PORT 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > CERTIFICATE_NAME.pem

Wo,

  • HOST_EMAIL ist die Serverdomäne , z. B. mail-server.com.

  • SECURE_PORT ist der Kommunikationsport, z. B. 587 oder 465

  • Dateiname der CERTIFICATE_NAME- Ausgabe (BASE 64 / PEM-Format)

SHoko
quelle