You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GKE Nginx Ingress指定Host后出现400无SSL证书错误排查

解决GKE Nginx Ingress指定Host时自签名客户端证书验证失败的问题

我来帮你拆解并解决这个问题——你遇到的400错误(提示“未发送所需SSL证书”),核心是自签名客户端证书与Nginx Ingress的SNI(Server Name Indication)配置不兼容导致的,以下是具体分析和解决步骤:

问题根源分析

当你在Ingress中指定rules.host: example.com时,Nginx Ingress Controller会为这个域名生成独立的SNI Server块。此时客户端请求通过Host: example.com触发SNI匹配,而你的自签名客户端证书缺少关键配置(比如与目标域名匹配的SAN字段),或者Nginx在SNI场景下没有正确加载客户端证书验证规则;而不指定Host时,请求匹配到Nginx的默认Server块,验证逻辑不受SNI限制,所以能正常执行。另外Cloudflare证书自带正确的SAN配置,因此不会出现这个问题。

具体解决步骤

1. 检查并修复客户端证书的SAN字段

Nginx在SNI场景下会验证客户端证书的**Subject Alternative Name(SAN)**是否与请求的Host匹配,自签名证书默认不会添加这个字段,这是最常见的原因。

验证当前证书的SAN:

openssl x509 -in my-cert.pem -text -noout | grep -A 3 "Subject Alternative Name"

如果没有输出,说明证书缺少SAN字段。

重新生成带SAN的客户端证书:

  • 创建一个扩展配置文件client-ext.cnf:
[client]
extendedKeyUsage = clientAuth
subjectAltName = DNS:example.com, IP:YOUR_MY_IP_VALUE  # 替换为你的实际IP
  • 修改你的证书生成脚本,引入这个配置:
#!/bin/bash
# 使用方式: ./build-client-cert.sh <证书名称> <有效期天数>
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.req -config client-ext.cnf  # 添加-config参数
openssl x509 -req -in client.req -CA rootCA.crt -CAkey rootCA.key -set_serial 101 -extensions client -extfile client-ext.cnf -days $2 -outform PEM -out client.cer  # 添加-extfile参数
openssl pkcs12 -export -inkey client.key -in client.cer -out $1.p12
rm client.key client.cer client.req

重新生成证书后,用之前的命令验证SAN字段是否存在。

2. 确认Ingress的CA证书Secret配置正确

确保存储可信CA的Secretclient-cert-api-ingress中的rootCA.crt是完整且格式正确的:

  • 检查Secret内容:
kubectl get secret client-cert-api-ingress -n development -o yaml

确认tls.crt字段是你的rootCA.crt的Base64编码(可以用base64 -d解码验证)。

  • 如果配置有误,重新创建Secret:
kubectl delete secret client-cert-api-ingress -n development
kubectl create secret generic client-cert-api-ingress -n development --from-file=tls.crt=rootCA.crt

3. 验证Nginx Controller的Server块配置

进入Nginx Controller Pod,检查对应example.com的Server块是否加载了客户端证书验证规则:

# 替换为你的Controller Pod名称
kubectl exec -it <nginx-ingress-controller-pod-name> -n ingress-nginx -- cat /etc/nginx/nginx.conf | grep -A 20 "server_name example.com"

确保输出中包含以下配置:

ssl_client_certificate /etc/ingress-controller/ssl/development-client-cert-api-ingress.pem;
ssl_verify_client on;
ssl_verify_depth 1;

如果没有这些配置,说明Ingress的Annotations没有正确应用,尝试删除并重新创建Ingress资源:

kubectl delete ingress api-ingress -n development
kubectl apply -f your-ingress-config.yaml

同时查看Controller日志排查错误:

kubectl logs <nginx-ingress-controller-pod-name> -n ingress-nginx

4. 优化curl请求参数

使用--resolve参数让curl正确发送SNI请求,避免手动Host头可能的冲突:

curl -k --cert my-cert.pem --key my-cert.key https://example.com/ --resolve example.com:443:MY_IP

这个命令会强制curl将example.com:443解析到你的MY_IP,同时自动发送正确的SNI和Host头。

总结

这个问题的核心是自签名客户端证书缺少与请求Host匹配的SAN字段,导致Nginx在SNI场景下拒绝证书。通过添加SAN字段、确认CA证书配置、验证Nginx Server块这几个步骤,就能解决指定Host时的400错误。

内容的提问来源于stack exchange,提问作者Montoya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 15:38:15