Nginx反向代理GitBlit客户端证书认证时SSL握手失败问题排查
结论
这个502错误既不是Nginx无法识别GitBlit的SSL证书,也不是单纯的用户端证书未传递,核心原因是:Nginx作为客户端连接GitBlit时未提供GitBlit要求的SSL客户端证书,导致GitBlit在SSL握手阶段主动断开连接。
原因拆解
排除Nginx验证上游证书的可能
你已经配置了proxy_ssl_verify off;,这会让Nginx跳过对GitBlit SSL证书的有效性校验,所以不存在Nginx无法识别GitBlit证书的问题。错误日志指向SSL握手失败
Nginx日志中的peer closed connection in SSL handshake while SSL handshaking to upstream表明:Nginx和GitBlit建立SSL连接时,GitBlit主动终止了握手。结合你直接访问GitBlit(提供客户端证书)能正常认证的情况,说明GitBlit的SSL配置要求所有连接必须提供客户端证书,但Nginx连接GitBlit时未携带任何客户端证书,因此被GitBlit拒绝。当前配置的缺陷
ssl_verify_client optional;仅控制Nginx对用户端的证书验证策略,并未配置Nginx在与上游GitBlit建立SSL连接时携带客户端证书——这是两个完全独立的SSL连接流程:- 第一个连接:用户 ↔ Nginx(Nginx验证用户证书)
- 第二个连接:Nginx ↔ GitBlit(GitBlit验证Nginx作为客户端的证书)
修复方案
需要在Nginx的location /git块中添加Nginx访问GitBlit时使用的客户端证书配置:
location /git { proxy_pass https://127.0.0.1:1111; # 保留原有proxy_set_header等配置... # 添加以下两行,指定Nginx连接GitBlit时使用的客户端证书和密钥 proxy_ssl_certificate D:\path\to\nginx-client-cert.pem; proxy_ssl_certificate_key D:\path\to\nginx-client-key.pem; }
注意:
- 这里的证书必须是被GitBlit的CA(即配置中的
ca.pem)签发的有效证书,GitBlit才会认可Nginx的连接。 - 如果GitBlit支持通过请求头接收用户证书信息(非常规SSL客户端证书认证场景),也可通过
proxy_set_header将用户证书传递给GitBlit,但这种方式无法替代SSL握手阶段的证书验证。
额外检查
确认GitBlit的SSL配置是否强制要求客户端证书:如果GitBlit设置了必须验证客户端证书,那么任何未携带有效证书的连接(包括Nginx的连接)都会在握手阶段被拒绝。
内容的提问来源于stack exchange,提问作者Bruce

