nginx ingress controller配置默认SSL证书

故障现象

线上某kubernetes集群环境,使用nginx-ingress-controller暴露了一个service,为一个API服务,其中在ingress对象中使用了TLS证书,使用浏览器输入ingress对应的域名访问这个API service,请求正常,但是某程序使用SDK调用此service,始终无法拿到结果。

ingress的yaml文件类似如下

image-20200606184834598

排查

  1. 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。

  2. 使用tcpdump对nginx-ingress-controller抓包,分析sdk请求时候的数据流,拿到抓包文件后用wireshark打开,发现如下错误信息。

    image-20200606184040298

image-20200606184203738分析此数据包,可以看出SDK客户端发出client_hello请求后,服务器端立马返回了报错,SSL握手未完成。

     3. 正常SSL握手过程如下图,结合抓包结果,可以发现服务器端nginx-ingress-controller没有返回server_hello信息给客户端,而是直接报错,日志信息则是提示未发现证书。

    4. 分析此ingress对应的yaml文件一切正常,同时从现象看,浏览器请求正常的,只是sdk调用异常,问题应该和客户端关联,于是对sdk请求时和浏览器请求时分别抓包的client_hello包进行对比,发现不同,sdk的client_hello包,extension字段未传递server_name.在openresty也搜到如下信息

    5. 综上,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引用的证书。

image-20200606214742276

参考:HTTPS 之 SSL/TLS 握手协议(Handshake Protocol)全过程解析

原文地址:https://www.cnblogs.com/360linux/p/13062044.html