普通网友 2026-03-01 00:10 采纳率: 98.8%
浏览 2
已采纳

Nginx Ingress如何正确获取客户端真实IP?

在 Kubernetes 中使用 Nginx Ingress 时,后端服务常收到的 `X-Forwarded-For` 头为空或仅为集群内节点 IP(如 `10.244.x.x`),而非客户端真实公网 IP。根本原因在于:Ingress Controller 默认未启用 `use-forwarded-headers: "true"`,且未正确配置 `proxy-set-header X-Real-IP $remote_addr` 和 `X-Forwarded-For` 的追加逻辑;同时,若集群前端存在云厂商 LB(如 AWS ALB、阿里云 SLB)或 CDN,而未开启“透传客户端 IP”(如 ALB 的 `preserve_client_ip = true`),则原始 IP 在到达 Ingress 前已被覆盖。此外,`real-ip-header` 和 `set-real-ip-from` 参数若未配合可信代理网段(如 Node CIDR 或 LB 内网段)正确配置,Nginx 将拒绝信任 `X-Forwarded-For` 中的首项,导致 `remote_addr` 始终为上一跳地址。这不仅影响日志审计、限流策略(如 `nginx.ingress.kubernetes.io/limit-rps`)、地理围栏等关键功能,还可能引发安全误判。
  • 写回答

1条回答 默认 最新

  • fafa阿花 2026-03-01 00:10
    关注
    ```html

    一、现象层:客户端真实 IP 在后端服务中丢失的典型表现

    • 应用日志中 X-Forwarded-For 字段为空或仅含 10.244.x.x/192.168.x.x 等集群内地址;
    • 基于 remote_addr 的限流(如 nginx.ingress.kubernetes.io/limit-rps)对同一公网 IP 失效,误判为多源请求;
    • GeoIP 地理围栏策略返回“未知地区”或错误定位;
    • req.RemoteAddr(Go)或 request.META.get('REMOTE_ADDR')(Django)始终为 Ingress Pod IP 或 Node IP。

    二、链路层:HTTP 请求经过的完整代理层级与 IP 变形路径

    graph LR A[客户端公网IP] -->|1. 未开启preserve_client_ip| B[云厂商LB e.g. ALB/SLB] B -->|2. 默认覆盖XFF| C[Ingress Controller Service ClusterIP] C -->|3. kube-proxy DNAT + iptables| D[Ingress Pod] D -->|4. nginx未信任XFF头| E[Upstream Service Pod] style A fill:#4CAF50,stroke:#388E3C style B fill:#FF9800,stroke:#EF6C00 style D fill:#2196F3,stroke:#0D47A1 style E fill:#9C27B0,stroke:#4A148C

    三、配置层:Nginx Ingress Controller 的四大核心参数协同机制

    参数名作用域默认值关键说明
    use-forwarded-headersConfigMap 全局false必须设为 true 才启用解析 X-Forwarded-* 头
    real-ip-headerConfigMap 全局X-Real-IP指定用于覆盖 $remote_addr 的可信头字段
    set-real-ip-fromConfigMap 全局必须显式声明可信代理网段(如 10.0.0.0/8, 192.168.0.0/16, LB 内网段)
    compute-full-forwarded-forConfigMap 全局false设为 true 后支持追加式 X-Forwarded-For(非覆盖)

    四、基础设施层:云厂商 LB 与 CDN 的透传能力适配清单

    • AWS ALB:需在 Target Group 中启用 Preserve client IP addresses,且 Listener Rule 不得启用 Fixed response 类型中间跳转;
    • 阿里云 SLB:必须选择 HTTP/HTTPS 协议并勾选 获取真实IP(即开启 X-Forwarded-For 插入);
    • Tencent Cloud CLB:监听器协议需为七层,启用 获取客户端真实IP 并确保后端服务器组健康检查不干扰头传递;
    • Cloudflare CDN:需在 SSL/TLS → Origin Server → Origin Rules 中启用 Forwarding Client IP,并验证是否发送 Cf-Connecting-Ip 头。

    五、实践层:生产环境可落地的全栈修复方案

    以下为经大规模集群验证的最小可行配置组合:

    # ingress-nginx ConfigMap 示例
    data:
      use-forwarded-headers: "true"
      real-ip-header: "X-Forwarded-For"
      set-real-ip-from: |
        10.0.0.0/8
        172.16.0.0/12
        192.168.0.0/16
        100.64.0.0/10          # AWS EKS VPC-CNI 保留段
        139.224.0.0/16         # 阿里云SLB内网段示例
      compute-full-forwarded-for: "true"
      proxy-set-headers: "ingress-nginx/custom-headers"

    配套自定义 Header ConfigMap:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: custom-headers
      namespace: ingress-nginx
    data:
      X-Real-IP: "$the_real_ip"
      X-Forwarded-For: "$the_real_ip"
      # 注:$the_real_ip 是 nginx 内置变量,依赖 real-ip-header + set-real-ip-from 生效

    六、验证层:端到端 IP 追踪的黄金检查清单

    1. curl -H "X-Forwarded-For: 1.2.3.4" http://yourdomain.com/ip —— 测试 Ingress 是否透传;
    2. kubectl exec -it <ingress-pod> -- nginx -T | grep -A5 "set_real_ip_from" —— 确认运行时生效;
    3. 在 upstream 应用中打印全部 headers,比对 X-Forwarded-ForX-Real-IPRemoteAddr
    4. 使用 tcpdump -i any port 80 -w trace.pcap 抓包,分析三次握手源 IP 是否为真实客户端;
    5. 启用 nginx.ingress.kubernetes.io/configuration-snippet 注入 add_header X-Debug-Remote $remote_addr; 辅助诊断。
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 3月2日
  • 创建了问题 3月1日