$ curl -v 'https://aa.com/'
* About to connect() to aa.com port 443 (#0)
* Trying 104.24.1.1... connected
* Connected to aa.com (104.24.1.1) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -12286
* Closing connection #0
* SSL connect error
curl: (35) SSL connect error
在新浪云上外网 HTTP 访问是通过我们的一个叫做 FetchURL 的服务来实现的。看下 FetchuURL 的日志,同样也是 SSL Handshake 时发生了问题,同时我们可以更清晰的看到是在 get server hello
的时候出错的。
SSL_do_handshake() failed (SSL: error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error)
GET_SERVER_HELLO
是什么意思?我们来看下 SSL/TLS 握手。
为了验证是不是 Client 不支持服务端的 TLS 版本和加密协议,我们使用 curl 指定一个比较强的加密协议: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
。
$ curl --ciphers ECDHE_ECDSA_AES_128_SHA -v 'https://aa.com' * About to connect() to aa.com port 443 (#0) * Trying 104.24.113.140... connected * Connected to aa.com (104.24.113.140) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none * SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA * Server certificate: * subject: CN=sni161691.aaa.com,OU=PositiveSSL Multi-Domain,OU=Domain Control Validated * start date: May 24 00:00:00 2016 GMT * expire date: Nov 27 23:59:59 2016 GMT * common name: sni161691.aa.com * issuer: CN=COMODO ECC Domain Validation Secure Server CA 2,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: aa.com > Accept: */*
成功!
通过修改并重新编译 FetchuURL 添加 TLS 版本和椭圆曲线公共密钥 (ECC) 加密算法。部署到测试环境后,抓该 URL 却依然返回 502。看了下错误日志还报 SSL_do_handshake() failed
。结合错误日志我们再理一下 FetchuURL 的逻辑,FetchuURL 是解析了域名后直接访问 IP:PORT。dig 了一下这个域名,解析后的 IP 也是正确的。在我本机通过 IP:PORT curl 的时候,发现有这么个警告 using IP address, SNI is being disabled by the OS
。看了下该网站是部署在了一个云计算平台上,可能用到了 SNI 支持多域名虚拟主机的 SSL/TLS 认证。因为我们就是这么搞的,在 ClientHello 阶段把 Host 带到 Server,Server 再加载对应 Host 的证书在 ServerHello 阶段把证书和公钥等信息发给 Client。
最后通过修改 FetchuURL 在 ClientHello 同时发送 Host,编译后部署到测试环境,这一次成功了。
转载请注明:爱开源 » 一个 SNI 导致的外网访问 502 问题的解决过程