在实际生产环境中,我们经常需要准确记录客户端的真实 IP 地址用于安全审计、访问分析等目的。本文将详细介绍如何通过配置 nginx-ingress 来获取并记录客户端的真实 IP。
问题背景
在 Kubernetes 集群中使用 nginx-ingress 作为入口控制器时,经常会发现访问日志中的客户端 IP 并不是真实的用户 IP,而是负载均衡器或中间代理的 IP。这是因为请求在到达应用之前,可能经过了多级代理:
客户端 → 云服务商负载均衡器 → nginx-ingress Pod → 业务应用 Pod在这个过程中,如果没有正确配置,nginx-ingress 只能看到前一跳(负载均衡器)的 IP 地址。
解决方案
通过在 nginx-ingress 的 ConfigMap 中添加以下配置,可以解决这个问题:
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
use-forwarded-headers: "true"
compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-proxy-protocol: "false" # 如果 LB 支持 PROXY 协议,可以设为 true
enable-real-ip: "true"
real-ip-header: "X-Forwarded-For"
real-ip-recursive: "true"配置详解
核心配置项说明
use-forwarded-headers: "true"启用对
X-Forwarded-*头部的处理这告诉 nginx 信任并使用上游代理设置的转发头部
compute-full-forwarded-for: "true"完整计算
X-Forwarded-For头部确保所有的代理 IP 都被正确记录在链条中
forwarded-for-header: "X-Forwarded-For"指定用于转发 IP 的头部字段
通常使用标准的
X-Forwarded-For
enable-real-ip: "true"启用真实 IP 模块
这是解析客户端真实 IP 的核心功能
real-ip-header: "X-Forwarded-For"指定包含真实 IP 的头部字段
与
forwarded-for-header保持一致
real-ip-recursive: "true"启用递归查找真实 IP
当存在多个代理时,会从右向左查找第一个不受信任的 IP
use-proxy-protocol: "false"是否启用 PROXY 协议
如果您的负载均衡器支持 PROXY 协议(如 AWS ELB、HAProxy),可以设置为
"true"
配置的安全考虑
这些配置通常不会影响现有的功能,因为:
向后兼容:这些配置主要是增强功能,不会破坏现有行为
渐进式增强:只是在现有日志基础上添加了更多信息
标准协议:使用的都是标准的 HTTP 头部和 nginx 指令
操作步骤
1. 编辑 ConfigMap
kubectl edit configmap ingress-nginx-controller -n ingress-nginx2. 添加配置项
在 data 部分添加上述配置:
data:
use-forwarded-headers: "true"
compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-proxy-protocol: "false"
enable-real-ip: "true"
real-ip-header: "X-Forwarded-For"
real-ip-recursive: "true"3. 重启 nginx-ingress Pod
配置更新后,需要重启 nginx-ingress 控制器以使配置生效:
kubectl rollout restart deployment/ingress-nginx-controller -n ingress-nginx或者删除 Pod 让 Deployment 自动重建:
kubectl delete pod -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx验证配置
方法一:检查 nginx 配置
# 进入 nginx-ingress pod
kubectl exec -it <ingress-pod-name> -n ingress-nginx -- cat /etc/nginx/nginx.conf
# 检查 real_ip 相关配置
kubectl exec -it <ingress-pod-name> -n ingress-nginx -- grep -i real_ip /etc/nginx/nginx.conf方法二:创建测试服务
创建一个简单的 echo 服务来验证接收到的头部信息:
apiVersion: v1
kind: Service
metadata:
name: echo-headers
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: echo-headers
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-headers
spec:
replicas: 1
selector:
matchLabels:
app: echo-headers
template:
metadata:
labels:
app: echo-headers
spec:
containers:
- name: echo-headers
image: mendhak/http-https-echo:latest
ports:
- containerPort: 8080访问该服务,检查返回的头部信息中的 x-forwarded-for 字段。
方法三:检查日志格式
确保日志格式包含真实 IP 信息:
# 可以同时配置自定义日志格式
data:
# ... 其他配置
log-format-upstream: '{"time": "$time_iso8601", "remote_addr": "$remote_addr", "real_ip": "$realip_remote_addr", "x_forwarded_for": "$http_x_forwarded_for", "status": "$status", "host": "$host", "path": "$uri"}'云服务商特殊配置
AWS ELB
如果使用 AWS ELB,需要额外配置:
# Service 配置
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
annotations:
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
spec:
type: LoadBalancer
externalTrafficPolicy: Local # 重要配置
# ... 其他配置同时在 ConfigMap 中启用 proxy protocol:
data:
use-proxy-protocol: "true"
# ... 其他配置其他云服务商
对于 GCP、Azure 等其他云服务商,确保正确设置 externalTrafficPolicy: Local:
spec:
externalTrafficPolicy: Local注意事项
性能影响:
externalTrafficPolicy: Local可能会影响负载均衡,但这是保留真实 IP 的必要配置安全考虑:确保只信任必要的代理,避免 IP 欺骗
测试验证:在生产环境应用前,务必在测试环境充分验证
监控告警:配置变更后,密切关注相关监控指标
总结
通过正确的 nginx-ingress 配置,我们可以可靠地获取客户端的真实 IP 地址。关键配置包括启用转发头部处理、设置真实 IP 解析参数,以及正确配置 Service 的 externalTrafficPolicy。
如果您在实施过程中遇到任何问题,欢迎在评论区留言讨论!
评论区