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

添加TLS证书到Envoy配置后gRPC连接失败及证书CN字段问题排查

问题说明

为Envoy添加TLS证书配置后,gRPC客户端出现连接错误:

code: 14,
metadata: Metadata { _internal_repr: {}, flags: 0 },
details: 'failed to connect to all addresses'

移除Envoy的TLS配置后请求可正常执行,同时使用grpcurl工具测试时提示:

Failed to dial target host "localhost:50000" x509: certificate relies on legacy Common Name field, use SANs instead

设置GODEBUG=x509ignoreCN=0后问题仍未解决。

Envoy相关配置(监听50000端口,转发至50052端口的itemService):

transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
          common_tls_context:
            tls_certificates:
              - certificate_chain:
                  filename: server.cert
                private_key:
                  filename: server.key

Node.js客户端代码(Next.js服务端getServerSideProps):

options = {
  key: readFileSync("certs/client.key"),
  cert: readFileSync("certs/ca.crt"),
  csr: readFileSync("certs/client.crt"),
};

const creds = credentials.createSsl(
  options.cert,
  options.key,
  options.csr
);

grpcServer.servicesList.itemsService = new ItemsServiceClient(
  "localhost:50000",
  creds,
  {
    "grpc.ssl_target_name_override": "localhost",
    "grpc.default_authority": "localhost",
  }
);

解决方案

1. 重新生成包含SAN字段的证书

现代TLS客户端(包括gRPC、grpcurl)已强制要求证书包含**Subject Alternative Name(SAN)**字段,仅使用旧的Common Name(CN)字段会导致验证失败,即使设置GODEBUG=x509ignoreCN=0也无法解决。

生成步骤:

  1. 创建openssl配置文件san.conf:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = localhost
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
  1. 用该配置重新生成服务端证书:
# 生成CSR和私钥
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -config san.conf
# 用CA签名生成证书
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.cert -days 365 -extensions v3_req -extfile san.conf

2. 修正Node.js客户端的SSL凭证参数顺序

credentials.createSsl的正确参数顺序为:createSsl(rootCerts, privateKey, certChain),当前代码参数传递错误,导致凭证无效。

调整后的代码:

options = {
  rootCert: readFileSync("certs/ca.crt"), // CA根证书
  clientKey: readFileSync("certs/client.key"), // 客户端私钥
  clientCert: readFileSync("certs/client.crt"), // 客户端证书
};

const creds = credentials.createSsl(
  options.rootCert,
  options.clientKey,
  options.clientCert
);

如果Envoy未配置客户端证书认证,可简化为仅传入CA根证书:

const creds = credentials.createSsl(readFileSync("certs/ca.crt"));

3. 完善Envoy的TLS配置(可选,若需客户端认证)

如果需要Envoy验证客户端证书,需添加CA证书配置:

transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
          common_tls_context:
            tls_certificates:
              - certificate_chain:
                  filename: server.cert
                private_key:
                  filename: server.key
            validation_context:
              trusted_ca:
                filename: ca.crt # 用于验证客户端证书的CA根证书
          require_client_certificate: true # 可选,强制客户端提供证书

4. 验证Envoy TLS监听状态

使用openssl工具检查Envoy的TLS端口是否正常:

openssl s_client -connect localhost:50000 -servername localhost

查看输出中是否包含正确的SAN字段,以及证书是否被CA信任。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:21:25