wireshark抓包-SSL握手
约 614 字大约 2 分钟...
wireshark抓包
SNI问题导致的网关层返回502错误
背景:
最近攻防等原因,运维将测试环境部分域名上了cloudflare(主要是海外)
业务方出现的问题:
在nginx中,这些域名被用做反向代理的upstream,在添加cloudflare之后,访问出现 http 502,具体配置如下
出错的nginx配置
location /proxy/cn/
{
proxy_pass https://user_cs_cn_backend/;
proxy_http_version 1.1;
proxy_set_header Host "api-cs-cn-sandbox.intsig.net";
proxy_set_header Connection "keep-alive";
proxy_connect_timeout 5;
proxy_send_timeout 10;
proxy_read_timeout 10;
}
upstream user_cs_cn_backend {
server api-cs-cn-sandbox.intsig.net:443;
keepalive 100;
}
最终定位到原因:
直接原因:跟cloudflare层的SSL握手失败 根本原因:nginx的配置错误、nginx本身没有正确处理SNI
如何解决:
在反向代理层添加
location /proxy/cn/ {
...
proxy_ssl_server_name on;
proxy_ssl_name "upstream-domain-name";
...
}
分析过程:
复现问题:
查看域名解析情况:
通过tcpdump进行抓包,在wireshark中打开
查看详细失败:
TLS握手失败错误码 40解读:
- 根本原因是 SNI 缺失,因为nginx在反向代理时,如果使用的是负载均衡的backend,默认会把host值、SNI传成backend的名称(user_cs_cn_backend),而不是真实的域名(巨坑)。
- SNI解读:
- SNI(Server Name Indication)允许客户端在TLS握手时指定要访问的域名,这样服务器可以返回正确的证书。
- 在反向代理中,如果后端服务(网关)使用不同的域名(网关需要设置为多个域名对应一个公网ip),代理服务器必须正确传递SNI信息,否则后端可能无法识别请求,导致握手失败。
- 基于这个原因,有两种处理方式:
- 不使用backend做负载均衡,而是直接写成对应域名。一般开发、测试环境可以这样操作。
location /proxy/cn/ { proxy_pass https://api-cs-cn-sandbox.intsig.net/; proxy_http_version 1.1; proxy_set_header Connection "keep-alive"; proxy_connect_timeout 5; proxy_send_timeout 10; proxy_read_timeout 10; }
- 设置正确的SNI信息,proxy_ssl_server_name、proxy_ssl_name。如果涉及backend存在多个域名,则需要结合map、变量,来设置proxy_ssl_name。
location /proxy/cn/ { ... proxy_ssl_server_name on; proxy_ssl_name "upstream-domain-name"; ... }
- 不使用backend做负载均衡,而是直接写成对应域名。一般开发、测试环境可以这样操作。