故障现象
线上某kubernetes集群环境,使用nginx-ingress-controller暴露了一个service,为一个API服务,其中在ingress对象中使用了TLS证书,使用浏览器输入ingress对应的域名访问这个API service,请求正常,但是某程序使用SDK调用此service,始终无法拿到结果。
ingress的yaml文件类似如下
![fcd8af4b2052c61c2f0fd19c6d30ecbb.png](https://i-blog.csdnimg.cn/blog_migrate/a2c912bdc22af233c62d38e0de232535.jpeg)
排查
- sdk调用ingress时nginx-ingress-controller的日志信息,发现有如下报错
2020/04/01 04:49:01 [error] 12173#12173: *6506108 [lua] cert.lua:58: no cert found for 443, context: ssl_certificate_by_lua*, client: x.x.x.x, server: 0.0.0.0:443 2020/04/01 04:49:01 [crit] 12173#12173: *6506107 SSL_do_handshake() failed (SSL: error:1417A179:SSL routines:tls_post_process_client_hello:cert cb error) while SSL handshaking, client: x.x.x.1x6, server: 0.0.0.0:443
google上述信息,没有找到相关case。
- 使用tcpdump对nginx-ingress-controller抓包,分析sdk请求时候的数据流,拿到抓包文件后用wireshark打开,发现如下错误信息。
![630885507cbc0435e3b9e9302950adc0.png](https://i-blog.csdnimg.cn/blog_migrate/ce5214dc09bc9b42f5050022ae64f82e.jpeg)
![677f5abea6966daf57bc2c94efd40a34.png](https://i-blog.csdnimg.cn/blog_migrate/137465051eea5c94efe5766947b66561.jpeg)
分析此数据包,可以看出SDK客户端发出client_hello请求后,服务器端立马返回了报错,SSL握手未完成。
- 正常SSL握手过程如下图,结合抓包结果,可以发现服务器端nginx-ingress-controller没有返回server_hello信息给客户端,而是直接报错,日志信息则是提示未发现证书。
![f6bababe74407238f723004ffdac8247.png](https://i-blog.csdnimg.cn/blog_migrate/708824f89499d8da04f831a8aaafae71.jpeg)
- 分析此ingress对应的yaml文件一切正常,同时从现象看,浏览器请求正常的,只是sdk调用异常,问题应该和客户端关联,于是对sdk请求时和浏览器请求时分别抓包的client_hello包进行对比,发现不同,sdk的client_hello包,extension字段未传递server_name.在openresty也搜到如下信息
![08d752b69b152f5ff016e68e0ade6401.png](https://i-blog.csdnimg.cn/blog_migrate/df9d08682290421dfa4f7e0989e6b125.jpeg)
- 综上,SDK客户端为非标准客户端,访问不带sni及server_name信息,导致nginx-ingress-controller无法通过sni和server_name找到对应的证书。
解决
长远看,需要SDK客户端解决请求不带server_name的问题。在nginx-ingress-controller无法通过sni和server_name找到对应的证书时,其会使用默认的端口证书,临时通过配置默认端口证书解决。在nginx-ingress-controller的启动参数,增加default-ssl-certificate指向此ingress引用的证书。
![abb4faab0a9e279e827db3f2bc24849a.png](https://i-blog.csdnimg.cn/blog_migrate/46f92abba591d0d532f90fabf3b3204e.jpeg)
参考:HTTPS 之 SSL/TLS 握手协议(Handshake Protocol)全过程解析