openssl Tool SSL analyse

应用 openssl 工具进行 SSL 故障分析 当前 SSL 协议有着广泛的运用,在 SSL 服务器的身份认证出现问题时,怎样才能有效快速的找出问题的根源呢?本文结合 openssl 提供的命令行工

应用 openssl 工具进行 SSL 故障分析 当前 SSL 协议有着广泛的运用,在 SSL 服务器的身份认证出现问题时,怎样才能有效快速的找出问题的根源呢?本文结合 openssl 提供的命令行工具 s_client,罗列了多种认证失败的情况,并给出了问题诊断的方法。

SSL 握手协议

首先简单的介绍一下 SSL 协议建立连接的过程。如图 1 所示,主要有如下几个过程: 图 1. SSL 身份认证及协商密钥的过程

∙ 客户端发起请求,包含一个hello 消息,并附上客户端支持的密码算法和 SSL 协议的版本消息以及用于生成密钥的随机数。 服务器收到消息后,服务器端选择加密压缩算法并生成服务器端的随机数,将该信息反馈给客户端;接着服务器端将自身的数字证书(在图 1 中使用了一个 X.509 数字证书)发送到客户端;完成上述动作后后服务器端会发送“hello done ”消息给客户端。此外如果服务器需要对客户端进行身份认证,服务器端还会发送一个请求客户端证书的消息。 一旦客户端收到”hello done ” , 就开始对服务器端的数字证书进行认证并检查服务器端选中的算法是可行的。如果服务器要求认证客户端身份,客户端还会发送自己的公钥证书。

,

∙ 如果对服务器的身份认证通过,客户端会发起密钥交换的请求。 服务器端和客户端根据先前协商的算法和交换随机数生成对称密钥进行后续的通信。

s_client 简介

openssl 提供了 SSL 协议的一个开放源代码的实现,包含三部分:ssl 库,加解密库和命令行工具。在命令行工具中 s_client 是一个以 SSL 协议连接远程服务器的客户端程序,该工具可以用于测试诊断。虽然 s_client 只提供了一些基础功能,但是其内部具体实现中使用了 ssl 库的大部分接口。 s_client命令行的语法为:

清单 1. 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]

常用参数的具体用途如下:

∙ -connect host:port :指定远程服务器的地址和端口,如果没有该参数,默认值为 localhost:443 ; -cert filename:若服务器端需要验证客户端的身份,通过 -cert 指定客户端的证书文件。 -key filename:指定私钥文件; -verify depth:打开服务器证书验证并定义证书验证过程中的最大深度。 -showcerts :显示服务器证书链; -CAfile filename:指定用于验证服务器证书的根证书; -state :打印出 SSL 会话的状态。

s_client 在 SSL 握手协议中的应用

在连接 SSL 服务器时最常见的问题就是客户端认证服务器端身份失败,有多种原因造成这些失败,以下列举了常见的错误并解析了如何应用 s_client 进行确诊。

∙ 服务器的证书在传输过程中被篡改

1. 提取服务器的证书:

在 linux 平台下创建脚本 retrieve-cert.sh 并存入一下清单 2 中的内容。该脚本的输出内容就是服务器端的 X509 证书经过 Base64 编码后的内容,执行脚本并将脚本输出存入文件 server.pem 中。 清单 2. 提取证书

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

,

1. 验证获取的证书,在命令行下执行”openss verify server.pem”。

如果证书内容被篡改,那么执行后的结果如清单 4 所示:

清单 4. 证书验证失败

[root@wks547385wss 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:

否则的话,我们就能得到认证通过,结果如下:

清单 5. 证书验证成功

[root@wks547385wss openssl]# openssl verify server.pem

server.pem: OK

客户端没有保存认证服务器端的证书的根证书;

1. 使用参数-state 检查是否在握手协议的证书认证时失败

清单 6. 显示 SSL 握手协议状态

[root@wks547385wss 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 。

清单 7. 获取服务器端的根证书

[root@wkswss 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再次连接服务器

清单 8. 设定服务器证书文件建立 SSL 连接

[root@wkswss 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)

客户端拥有认证服务器证书的根证书,但是服务器被防火墙隔离,防火墙在收到来自客户端的 SSL 连接请

求时返回防火墙的证书。这种情况下的症状跟服务器证书被篡改非常相似,但是区别在于应用上述提及的方法仍然不能定位错误。

1. 客户端已经拥有服务器 build.rchland.ibm.com 的根证书rochCA.pem ,当客户端试图连接服务器客户时,对服务器的证书认证却不能通过。

清单 9. 认证失败

[root@wks547385wss 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 所示。 清单 10. 解码根证书

[root@wks547385wss 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 无疑给程序员带来了一把利刃,特别是缺乏调试工具的环境下,如嵌入式系统。 参考资料

∙ ∙

∙ ∙

∙ 提供了 SSL 协议的简介、握手协议和主要报文格式 公钥体系架构简介 如果需要了解 X509 证书的细节,查看 使用完全解析 更多了解 openssl 可查阅 在 寻找为 Linux 开发人员(包括 )准备的更多参考资料,查阅我们 最受欢迎的文章和教程。 在 developerWorks 上查阅所有 和 。

标签: