客户端与服务端均配置证书私钥时gRPC安全连接失败如何解决
gRPC TLS握手故障原因及解决方案
故障根因
- 服务器名称匹配失败:你当前使用IP地址
192.168.37.137访问gRPC服务,但现有证书存在两个匹配问题:- 证书的通用名称(CN)为通配符
*,TLS标准中通配符CN仅支持匹配域名,不支持匹配IP地址 - 证书未添加
Subject Alternative Name(SAN/使用者备用名称)扩展,无法关联IP地址,因此服务端在校验SNI时找不到匹配的服务器名称,直接中断握手
- 证书的通用名称(CN)为通配符
- 证书已过期:从证书有效期可以看到,证书的有效时间为
2021年11月8日~2022年11月8日,当前时间已远超失效时间,即使地址匹配也会触发校验失败 - 证书使用不规范(非直接报错原因):你的证书配置了
Basic Constraints: CA:TRUE,属于CA根证书属性,直接用作服务端/客户端的通信实体证书不符合X509证书使用规范
排查步骤
- 执行裸TLS握手验证:运行命令
openssl s_client -connect 192.168.37.137:<你的gRPC服务端口> -showcerts,如果返回同样的证书校验错误,即可排除gRPC代码逻辑问题,确认故障由证书配置导致 - 验证证书有效期:运行命令
openssl x509 -in <证书文件路径> -dates -noout,确认证书是否在有效时间范围内 - 验证SAN扩展:运行命令
openssl x509 -in <证书文件路径> -text -noout | grep -A 10 "Subject Alternative Name",确认扩展中是否包含你访问使用的IP地址
解决方案
1. 重新生成符合规范的证书
首先创建SAN扩展配置文件san.cnf,按需替换其中的国家、组织、IP地址等信息:
[req] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn req_extensions = req_ext [dn] C = IT ST = Itali O = Uni CN = 192.168.37.137 [req_ext] subjectAltName = @alt_names basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth [alt_names] IP.1 = 192.168.37.137 # 如有多个访问IP/域名,可按格式新增:IP.2 = x.x.x.x、DNS.1 = xxx.com
按如下步骤生成证书:
- 生成服务端私钥与证书签名请求:
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -config san.cnf - 用现有CA证书签发服务端证书(如果是自签场景,直接把签发命令中的CA参数替换为自签CA的证书和私钥即可):
openssl x509 -req -in server.csr -CA <你的CA证书路径> -CAkey <你的CA私钥路径> -CAcreateserial -out server.crt -days 3650 -extensions req_ext -extfile san.cnf - 双向认证场景下的客户端证书按同样逻辑生成,只需调整
alt_names为客户端的IP/标识即可。
2. 调整gRPC配置
- 服务端加载自身的私钥、证书,以及信任的CA证书(用于校验客户端证书)
- 客户端加载自身的私钥、证书,以及信任的CA证书(用于校验服务端证书);单向认证场景下客户端仅需加载CA证书即可
- 测试场景临时验证可临时关闭校验(生产环境禁止使用):Python客户端创建通道时添加参数
options=[('grpc.ssl_target_name_override', '*')],或者直接使用不安全通道grpc.insecure_channel。
3. 验证修复
首先用openssl s_client命令重新测试TLS握手,确认无报错后再启动gRPC服务和客户端验证通信。
内容的提问来源于stack exchange,提问作者LVZftm
相关产品推荐
相关产品推荐

