opensslを使用してサーバーから証明書を取得する


354

リモートサーバーの証明書を取得しようとしています。これを使用してキーストアに追加し、Javaアプリケーション内で使用できます。

シニア開発者(休暇中:()がこれを実行できることを私に知らせました:

openssl s_client -connect host.host:9999

生の証明書をダンプして、それをコピーしてエクスポートできます。次の出力が表示されます。

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:

私もこのオプションを試しました

-showcerts 

そして、これ(debian mind youで実行)

-CApath /etc/ssl/certs/ 

しかし、同じエラーが発生します。

このソースは、私はそのCApathフラグを使用することができると言いますが、助けにはならないようです。私は無駄に複数のパスを試してみました。

どこが悪いのか教えてください。

回答:


463

SNIを使用

リモートサーバーがSNIを使用している(つまり、単一のIPアドレスで複数のSSLホストを共有している)場合、正しい証明書を取得するには、正しいホスト名を送信する必要があります。

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

SNIなし

リモートサーバーがSNIを使用していない場合は、-servernameパラメーターをスキップできます。

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


サイトの証明書の詳細をすべて表示するには、次の一連のコマンドも使用できます。

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

3
うーん。そのコマンドを実行すると、同じエラーが発生します。私のopensslバージョンが「OpenSSL 0.9.8g 2007年10月19日」であることに気付きました。あなたはなにか考えはありますか?
厄介なペースト

39
便利: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
madboa.comからの代替の便利なスクリプト:echo | openssl s_client -connect server:port 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cert.pem
rmeakins 2013

9
このビットより簡潔を作成するには、置き換えることができsedopenssl x509、そしてサブシェルを使用してそれを読む:openssl x509 -in <(openssl s_client -connect server:port -prexit 2>/dev/null)
ゲイブ・マーティン・Dempesy

27
またecho | openssl s_client -connect google.com:443 2>/dev/null | openssl x509
MattSizzle 2014年

68

私はアリの答えに同意します(そしてそれを支持しました:)が、それをWindowsでJavaで動作させるために追加の手順を実行する必要がありました(展開する必要がある場所):

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

openssl x509 -outform DER変換を追加する前に、Windowsのkeytoolから、証明書の形式についてエラーが発生しました。.derファイルのインポートは正常に機能しました。


奇数。Java 6以降、WindowsのkeytoolでPEM証明書を使用しており、問題に直面することはありません。
imgx64 2017年

39

ここにはもっと複雑なことがわかります。これを実現するには、さらに多くの詳細を提供する必要がありました。クライアント認証を必要とする接続と、ハンクシェイクが証明書がダンプされた段階に進むには、より多くの情報が必要だったという事実と関係があると思います。

これが私の作業コマンドです:

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

うまくいけば、これはいくつかのより多くの情報で行うことができる誰にとっても正しい方向へのナッジです。


6
申し訳ありませんが、あなたの答えはあまり意味がありません。証明書を取得するためにサーバーに証明書を渡す必要がありましたか?
Ari Maniatis

2
うん。クライアント認証AFAIK。
厄介なペーストリー

11
「-prexit」はそのデータも返すことがわかりました。例えば; openssl s_client -connect host:port -prexit
Robert

39

PEM形式でリモートサーバーから証明書を抽出するワンライナー。今回は次のものを使用しsedます。

openssl s_client -connect www.google.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

2
これは、証明書を抽出するのにほぼ完璧ですが、-servernameオプションがないだけで、理由はわかりませんが、完全な証明書を取得するために使用する必要がありました。
Karl.S

-servernameは、サーバー名表示(SNI)に必要です。残りの部分でWeb検索を拡張できます。
サムグレスケ

32

キーストアに追加するためのPEM出力と人間が読める出力が含まれ、HTTPサーバーで作業している場合に重要であるSNIもサポートする、このための最も簡単なコマンドラインは次のとおりです。

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

-servernameオプションは、SNIをサポートして有効にすることです-textのopensslのx509人間が読める形式で証明書を出力します。


-servernameにサブドメインを追加できます。たとえば、example.comではなくws.example.comです(これを-connectパラメータにも適用します)。
ラッセルホフ2017年

24

リモートサーバーの証明書を取得するには、使用できるopensslツールを、あなたはの間でそれを見つけることができますBEGIN CERTIFICATEし、END CERTIFICATEあなたの証明書ファイル(CRT)にコピー&ペーストする必要があります。

これを示すコマンドは次のとおりです。

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

チェーンからすべての証明書を返すには、次のgように(グローバル)を追加します。

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

次に、証明書ファイル(file.crt)をキーチェーンにて信頼できるようにするだけでよいので、Javaは文句を言わないはずです。

OS Xでは、ファイルをダブルクリックするか、キーチェーンアクセスにドラッグアンドドロップして、ログイン/証明書に表示されるようにします。次に、インポートされた証明書をダブルクリックして、[ SSLを常に信頼する]にします。

CentOS 5 では、それらを/etc/pki/tls/certs/ca-bundle.crtファイルに追加して(そして実行sudo update-ca-trust force-enableする:)、またはCentOS 6ではそれらをにコピーして/etc/pki/ca-trust/source/anchors/実行することができますsudo update-ca-trust extract

Ubuntuでは、それらをにコピーして/usr/local/share/ca-certificates実行しsudo update-ca-certificatesます。


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

6

証明書チェーンのみを印刷し、サーバーの証明書は印刷しない場合:

# 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}'

CentOS / RHEL 6/7でCAの信頼を更新するには:

# 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

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

CentOS7でまさに必要なもの。ありがとう!
Arthur Hebert

5

次のbashスクリプトを使用して、サーバールート証明書を取得して保存できます。

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'") }'

必要な変数を上書きするだけです。


4

サーバーが電子メールサーバー(MS ExchangeまたはZimbra)の場合はstarttlssmtpフラグとフラグを追加する必要があります。

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

どこ、

  • HOST_EMAILは、mail-server.comなどのサーバードメインです。

  • SECURE_PORTは、587または465などの通信ポートです。

  • CERTIFICATE_NAME出力のファイル名(BASE 64 / PEM形式)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.