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

如何配置两台NGINX传递客户端证书至后端应用?

问题解答

可行性结论

这个场景完全可以通过NGINX配置实现,核心是确保客户端证书信息在两台NGINX间正确传递,同时规避NGINX默认请求头处理逻辑的干扰。

两台NGINX具体配置方案

1. NGINX-A(前端反向代理)配置

先确保NGINX-A开启双向SSL认证,再将原始客户端证书处理后放入请求头转发至NGINX-B:

server {
    listen 443 ssl;
    server_name your-domain.com;

    # 双向SSL认证配置
    ssl_certificate /path/to/nginx-a-cert.pem;
    ssl_certificate_key /path/to/nginx-a-key.pem;
    ssl_client_certificate /path/to/ca-cert.pem; # 验证客户端证书的CA根证书
    ssl_verify_client on; # 强制开启双向认证

    location / {
        proxy_pass https://nginx-b-ingress-address;
        # NGINX-A与NGINX-B之间也开启双向认证
        proxy_ssl_certificate /path/to/nginx-a-client-cert.pem;
        proxy_ssl_certificate_key /path/to/nginx-a-client-key.pem;
        proxy_ssl_trusted_certificate /path/to/nginx-b-ca-cert.pem;
        proxy_ssl_verify on;

        # 传递原始客户端证书:处理换行符避免HTTP头截断
        proxy_set_header X-Original-Client-Cert $ssl_client_cert;
        # 兼容NGINX-B默认的ssl-client-cert字段
        proxy_set_header ssl-client-cert $ssl_client_cert;
        # 可选:传递客户端证书的DN信息
        proxy_set_header X-Client-DN $ssl_client_s_dn;
    }
}

注意:$ssl_client_cert包含带换行的PEM格式证书,部分代理会截断换行,可借助ngx_http_set_misc_module统一格式:

set $formatted_cert $ssl_client_cert;
replace $formatted_cert '\n' '\n';
proxy_set_header ssl-client-cert $formatted_cert;

2. NGINX-B(K8S Ingress NGINX)配置

NGINX-B默认会将自身SSL连接拿到的客户端证书(即NGINX-A的证书)转发给上游,需修改配置,用NGINX-A传递的原始证书覆盖默认字段:

方式1:Ingress Annotation配置(推荐)

在K8S Ingress资源中添加以下注解:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-b-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-verify-client: "on" # 开启与NGINX-A的双向认证
    nginx.ingress.kubernetes.io/ssl-certificate: "namespace/nginx-b-cert-secret"
    nginx.ingress.kubernetes.io/ssl-client-certificate: "namespace/ca-cert-secret" # 验证NGINX-A证书的CA
    # 覆盖默认的ssl-client-cert转发逻辑
    nginx.ingress.kubernetes.io/proxy-set-header: "ssl-client-cert $http_x_original_client_cert"
    # 确保自定义头不被丢弃
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header ssl-client-cert $http_ssl_client_cert;

方式2:自定义NGINX配置片段

若注解不够灵活,可通过ConfigMap添加自定义配置:

server {
    # 保留Ingress默认配置...

    # 开启与NGINX-A的双向认证
    ssl_client_certificate /etc/nginx/ssl/ca-cert.pem;
    ssl_verify_client on;

    location / {
        # 使用NGINX-A传递的原始证书覆盖默认字段
        proxy_set_header ssl-client-cert $http_x_original_client_cert;
        # 可选:保留NGINX-A的证书信息用于审计
        proxy_set_header X-Nginx-A-Cert $ssl_client_cert;
    }
}

NGINX对ssl-client-cert等请求头的处理逻辑

  1. 变量优先级规则:当NGINX开启双向认证时,$ssl_client_cert存储的是当前直接连接的客户端证书(比如NGINX-B的该变量是NGINX-A的证书,而非原始客户端的),因此必须手动传递原始证书的请求头,不能依赖NGINX默认转发。
  2. 请求头标准化:NGINX默认会将请求头中的下划线转为连字符(如X_Original_Client_Cert会被转为X-Original-Client-Cert),传递时尽量使用连字符格式,或在配置中明确指定头名。
  3. 头过滤机制:NGINX反向代理时默认会丢弃部分敏感头,自定义头必须通过proxy_set_header显式设置才能传递到上游。
  4. 证书格式兼容:PEM格式证书含换行符,直接放入HTTP头可能被解析为多个头或截断,需统一换行格式(如替换为\n),确保上游应用能正确解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:25:43