當前 SSL 協議有著廣泛的運用,在 SSL 伺服器的身份認證出現問題時,怎樣才能有效快速的找出問題的根源呢?本文結合 openssl 提供的命令行工具 s_client,羅列了多種認證失敗的情況,並給出了問題診斷的方法。
SSL 握手協議
首先簡單的介紹一下 SSL 協議建立連接的過程。如圖 1 所示,主要有如下幾個過程:
![]() ![]() |
s_client 簡介
openssl 提供了 SSL 協議的一個開放源代碼的實現,包含三部分:ssl 庫,加解密庫和命令行工具。在命令行工具中 s_client 是一個以 SSL 協議連接遠程伺服器的客戶端程序,該工具可以用於測試診斷。雖然 s_client 只提供了一些基礎功能,但是其內部具體實現中使用了 ssl 庫的大部分介面。
s_client命令行的語法為:
openssl s_client [-connect host:port>] [-verify depth] [-cert filename] [-key filename] [-CApath directory] [-CAfile filename][-reconnect] [-pause] [-showcerts] [-debug] [-msg] [-nbio_test] [-state] [-nbio] [-crlf] [-ign_eof] [-quiet] |
常用參數的具體用途如下:
![]() ![]() |
s_client 在 SSL 握手協議中的應用
在連接 SSL 伺服器時最常見的問題就是客戶端認證伺服器端身份失敗,有多種原因造成這些失敗,以下列舉了常見的錯誤並解析了如何應用 s_client 進行確診。
在 linux 平台下創建腳本 retrieve-cert.sh 並存入一下清單 2 中的內容。該腳本的輸出內容就是伺服器端的 X509 證書經過 Base64 編碼后的內容,執行腳本並將腳本輸出存入文件 server.pem 中。
###usage: retrieve-cert.sh remote.host.name [port] SSLHOST=$1 SSLPORT=${2:-443} echo |\ openssl s_client -connect ${SSLHOST}:${SSLPORT} 2>&1 |\ sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' |
如果證書內容被篡改,那麼執行后的結果如清單 4 所示:
[[email protected] openssl]# openssl verify server.pem unable to load certificate 19280:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:947: 19280:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:304:Type=X509 19280:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:pem_oth.c:82: |
否則的話,我們就能得到認證通過,結果如下:
[[email protected] openssl]# openssl verify server.pem server.pem: OK |
1. 使用參數-state檢查是否在握手協議的證書認證時失敗
[[email protected] openssl]# openssl s_client -connect www6.software.ibm.com:443 -state CONNECTED(00000003) SSL_connect:before/connect initialization SSL_connect:SSLv2/v3 write client hello A SSL_connect:SSLv3 read server hello A depth=1 /C=US/O=Equifax/OU=Equifax Secure Certificate Authority verify error:num=19:self signed certificate in certificate chain verify return:0 SSL_connect:SSLv3 read server certificate A SSL_connect:SSLv3 read server done A SSL_connect:SSLv3 write client key exchange A SSL_connect:SSLv3 write change cipher spec A SSL_connect:SSLv3 write finished A SSL_connect:SSLv3 flush data SSL_connect:SSLv3 read finished A |
2. 運用 s_client 參數-showcerts獲取伺服器端的根證書,伺服器端的證書鏈將會全部顯示出來,在證書鏈的末端就是根證書,保存證書文件為serverCA.pem 。
[[email protected] openssl]# openssl s_client -connect www6.software.ibm.com:443 – showcerts … s:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- |
3. 運用 s_client 參數-CAfile CA.pem再次連接伺服器
[[email protected] openssl]# openssl s_client -CAfile serverCA.pem -connect www6.software.ibm.com:443 -state CONNECTED(00000003) SSL_connect:before/connect initialization SSL_connect:SSLv2/v3 write client hello A SSL_connect:SSLv3 read server hello A depth=1 /C=US/O=Equifax/OU=Equifax Secure Certificate Authority verify return:1 depth=0 /C=US/O=IBM/CN=www6.software.ibm.com verify return:1 SSL_connect:SSLv3 read server certificate A SSL_connect:SSLv3 read server done A SSL_connect:SSLv3 write client key exchange A SSL_connect:SSLv3 write change cipher spec A SSL_connect:SSLv3 write finished A SSL_connect:SSLv3 flush data SSL_connect:SSLv3 read finished A …… SSL-Session: Protocol : TLSv1 Cipher : DES-CBC3-SHA Session-ID: 00365044871540E334826923BF9C531CE659274858585858499C14380000000C Session-ID-ctx: Master-Key: D065F1F2297560F1CD4CCC0D7A58E647CC9F596BCEC545CF90DD54659CB36C53CDAC977E5784C6 A273BA28B486E578B9 Key-Arg : None Krb5 Principal: None Start Time: 1234986898 Timeout : 300 (sec) Verify return code: 0 (ok) |
1. 客戶端已經擁有伺服器 build.rchland.ibm.com 的根證書rochCA.pem,當客戶端試圖連接伺服器客戶時,對伺服器的證書認證卻不能通過。
[[email protected] openssl]# openssl s_client -CAfile roch.pem -state -connect build.rchland.ibm.com:443 CONNECTED(00000003) SSL_connect:before/connect initialization SSL_connect:SSLv2/v3 write client hello A SSL_connect:SSLv3 read server hello A depth=0 /serialNumber=93e352/CN=rch-fw-1a.rchland.ibm.com/unstructuredName= rch-fw-1a.rchland.ibm.com verify error:num=18:self signed certificate verify return:1 depth=0 /serialNumber=93e352/CN=rch-fw-1a.rchland.ibm.com/unstructuredName= rch-fw-1a.rchland.ibm.com verify return:1 SSL_connect:SSLv3 read server certificate A SSL_connect:SSLv3 read server done A SSL_connect:SSLv3 write client key exchange A SSL_connect:SSLv3 write change cipher spec A SSL_connect:SSLv3 write finished A SSL_connect:SSLv3 flush data SSL_connect:SSLv3 read finished A … |
2. 使用x509工具,查看根證書的具體內容,特別是證書籤發者和持有者的身份,如清單 10 所示。
[[email protected] openssl]# openssl x509 -text -in roch.pem Certificate: Data: Version: 3 (0x2) Serial Number: 903804111 (0x35def4cf) Signature Algorithm: sha1WithRSAEncryption Issuer: C=US, O=Equifax, OU=Equifax Secure Certificate Authority Validity Not Before: Aug 22 16:41:51 1998 GMT Not After : Aug 22 16:41:51 2018 GMT Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) |
有了上述的證書籤發者信息后,我們的問題就迎刃而解了,客戶端收到了來自防火牆的證書,該證書和防火牆後面的伺服器的數字證書來自不同的簽發者。
![]() ![]() |
結束語
openssl 提供的 ssl 庫被廣泛的運用的同時,也增加了程序員在診斷通訊故障的難度。巧妙的運用 s_client 無疑給程序員帶來了一把利刃,特別是缺乏調試工具的環境下,如嵌入式系統。(責任編輯:A6)
[火星人 ] 應用 openssl 工具進行 SSL 故障分析已經有2071次圍觀