CloudFlare 关于debugging,testing和使用HTTP / 2的工具的博客文章提到了这种方法来找出给定服务器支持哪些协议:
$ openssl s_client -connect www.cloudflare.com:443 -nextprotoneg '' CONNECTED(00000003) Protocols advertised by server: h2, spdy/3.1, http/1.1
这种方法似乎对我testing过的很多领域都很好。 然而,(HTTP / 2-enabled)域名benchmarkjs.com产生的输出看起来完全不同,我不知道为什么:
$ openssl s_client -connect benchmarkjs.com:443 -nextprotoneg '' CONNECTED(00000003) depth=0 C = US, ST = Washington, L = Seattle, O = Odin, OU = Plesk, CN = Plesk, emailAddress = [email protected] verify error:num=18:self signed certificate verify return:1 depth=0 C = US, ST = Washington, L = Seattle, O = Odin, OU = Plesk, CN = Plesk, emailAddress = [email protected] verify return:1 --- Certificate chain 0 s:/C=US/ST=Washington/L=Seattle/O=Odin/OU=Plesk/CN=Plesk/[email protected] i:/C=US/ST=Washington/L=Seattle/O=Odin/OU=Plesk/CN=Plesk/[email protected] --- Server certificate -----BEGIN CERTIFICATE----- MIIDfTCCAmUCBFXIlUswDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMRMw EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMQ0wCwYDVQQKDARP ZGluMQ4wDAYDVQQLDAVQbGVzazEOMAwGA1UEAwwFUGxlc2sxHTAbBgkqhkiG9w0B CQEWDmluZm9AcGxlc2suY29tMB4XDTE1MDgxMDEyMTMwMFoXDTE2MDgwOTEyMTMw MFowgYIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH DAdTZWF0dGxlMQ0wCwYDVQQKDARPZGluMQ4wDAYDVQQLDAVQbGVzazEOMAwGA1UE AwwFUGxlc2sxHTAbBgkqhkiG9w0BCQEWDmluZm9AcGxlc2suY29tMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvLgc48tQHJaVZj4btZhGySqNlQeXRti8 Nansm15wJXS45EIFx6lYqFbDjD22VBwwDrILNZBY9BiKLV+VsZYuu1sOK+Ctatww gcOf4UB5pT6kOP48vBJlsaxqf+kCQpiVBniliLs7yAxl3BjjzQBluI4DUMXGpsuD u2tBi/fsUV6QRBzsebQ6cH5cZ9XPGiirPyFe7yNNbXurooYmeD1YjEH6qYIPhU9O lTOU9rssii8ShmHL/X54ekIqZ9y5b3eD+Dhp45/WjxXcgSxWZHx8SYcKndiSOJFa KUXlBKREmvH1nQLtp1BdCH6BiLPXaMMcRPY1BUhLSLt6M68B5vRDqQIDAQABMA0G CSqGSIb3DQEBCwUAA4IBAQAvTuPoc0RYHXeHW61s6PPC7pRtp1t+roknJPa/po1P vFtINtR9vuCfeUfS7K8ryfduBkX/km8qjCxjNvjQsJdya5mfMdPzW4AabJs06qUp h5PPk2ER1OcPzraemcHHL8gzStVk3n9C23ZRAwZaEIsgnOQ58YGf4eyrzKXBClfL NPL28cQQH5+d4lIsQc7B9d0OiiUQNTBfVD/CA67SPvc/f6Xq7ARdrc44GhA03cUN 0Vr60j2kv9IkdSnRPtt40R8AD97bKu9E/jOJCrSOfCbB3Qz1Pdm2lZqSEnoHdlbg 2KY8HrvoEXvuPUNXRIQEhpR7f9y70iBPORs0PbuC+qDf -----END CERTIFICATE----- subject=/C=US/ST=Washington/L=Seattle/O=Odin/OU=Plesk/CN=Plesk/[email protected] issuer=/C=US/ST=Washington/L=Seattle/O=Odin/OU=Plesk/CN=Plesk/[email protected] --- No client certificate CA names sent Peer signing digest: SHA512 Server Temp Key: ECDH, P-256, 256 bits --- SSL handshake has read 1409 bytes and written 448 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: C0474D42297C21B374C558E698A69EEBBFF537B35E6365D31B4D7AA2CD4192AD Session-ID-ctx: Master-Key: 2292DF581DAE3CE4A4E8CFF5A351A3F4E99602A7DCDBD090998C38926498743B4E3A808A1C4505136D51FC847F0153A6 Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None Start Time: 1455103745 Timeout : 300 (sec) Verify return code: 18 (self signed certificate) ---
请注意,它不会返回到提示; 你连接到服务器,现在可以进入例如GET / HTTP/1.1然后是Host: benchmarkjs.com 。
所以,我的两个问题是:
benchmarkjs.com有什么不同,使这种技术无法正常工作? openssl s_client以通用的方式检测HTTP / 2支持,即使对于这个域也是如此? 我的意思是: openssl s_client手册指出:
-nextprotoneg协议
启用Next Protocol Negotiation TLS 扩展,并提供客户端应该支持的以逗号分隔的协议名称列表。 该列表应该首先包含最想要的协议。 协议名称是可打印的ASCIIstring,例如“http / 1.1”或“spdy / 3”。 协议的空列表被特别处理,并且会导致客户端通告对TLS扩展的支持,但是在将ServerHello与服务器支持的协议列表一起收回之后将断开连接。
(强调我的)
所以我会说在benchmarkjs.com终止您的请求的SSL / TLS引擎不支持下一个协议协商扩展或由于某种原因禁用。 因此,在你的testing中, openssl s_client命令openssl s_client支持NPN,但是服务器对ot不起作用。 握手仍然通过确定,因为扩展看起来不是必需的(或者至less被openssl认为是这样),并且你得到连接的TLS隧道。
至于实现可靠的检查,恐怕因为openssl s_client显然没有任何命令行选项,迫使它立即终止会话,你将不得不深入到一个水平,编写自己的程序链接到libssl将执行期望的行为。 (而且我会亲自在Go中使用它的标准库的crypto/tls包来实现它,因为它不比JavaScript编程更困难,但是产生了一个静态链接的程序,意味着没有脑子的部署。