在Nginx Ingress前置AWS ELB场景下,如何基于客户端真实IP配置Ingress源地址白名单?
结合你的架构(Client -> AWS ELB -> Nginx Ingress -> Pod)和需求,我推荐两个完全在Kubernetes内部实现的方案,都支持CIDR范围白名单,不需要切换NLB、修改安全组或依赖Cloudflare:
方案一:直接基于X-Forwarded-For头做白名单验证
这个方案不需要修改源IP,而是通过Nginx的自定义配置让白名单规则直接检查X-Forwarded-For里的真实客户端IP,灵活性更高。
操作步骤:
先确保Nginx Ingress信任ELB的IP
不管用哪个方案,第一步都要让Ingress Controller认可ELB是可信代理,这样它才会信任X-Forwarded-For头的内容。如果是Helm部署的Ingress Controller,在values.yaml里添加以下配置:controller: config: use-forwarded-headers: "true" proxy-real-ip-cidr: "10.0.0.0/16" # 替换成你的ELB所在VPC的CIDR或ELB的公网IP段proxy-real-ip-cidr用来指定哪些上游IP是可信的,只有来自这些IP的请求,Nginx才会处理X-Forwarded-For头。给目标Ingress添加自定义白名单规则
使用nginx.ingress.kubernetes.io/configuration-snippet注解,写入Nginx规则检查X-Forwarded-For的第一个IP(也就是真实客户端IP)是否在白名单CIDR内:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: your-app-ingress annotations: nginx.ingress.kubernetes.io/configuration-snippet: | # 提取X-Forwarded-For中的第一个IP(处理多层代理场景) split $http_x_forwarded_for $client_real_ip; # 初始化标记为不允许 set $allowed 0; # 匹配白名单CIDR,多个用|分隔 if ($client_real_ip ~* ^(192.168.1.0/24|10.5.0.0/16)$) { set $allowed 1; } # 不匹配则返回403 if ($allowed = 0) { return 403; } spec: ingressClassName: nginx rules: - host: your-app.example.com http: paths: - path: / pathType: Prefix backend: service: name: your-app-service port: number: 80这里的
split指令会把X-Forwarded-For按逗号分割,取第一个IP作为真实客户端IP;正则表达式里的CIDR可以根据你的需求自由添加,用|分隔即可。
方案二:让Nginx将源IP替换为X-Forwarded-For中的真实IP
如果你更想用Ingress原生的whitelist-source-range字段,这个方案可以让Nginx把请求的源IP替换成X-Forwarded-For里的真实IP,这样原生的白名单配置就会生效。
操作步骤:
配置Ingress Controller替换真实IP
同样先信任ELB的IP,再添加real-ip-header和set-real-ip-from配置(Helm的values.yaml):controller: config: use-forwarded-headers: "true" proxy-real-ip-cidr: "10.0.0.0/16" # 替换成你的ELB CIDR real-ip-header: "X-Forwarded-For" # 指定从哪个头取真实IP set-real-ip-from: "10.0.0.0/16" # 和proxy-real-ip-cidr一致,指定可信代理范围配置后,Nginx会把请求的源IP替换为
X-Forwarded-For中的第一个IP,后续所有基于源IP的规则(包括whitelist-source-range)都会使用这个真实IP。使用原生的whitelist-source-range字段
现在就可以像平时一样在Ingress里配置白名单CIDR了:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: your-app-ingress spec: ingressClassName: nginx whitelist-source-range: 192.168.1.0/24,10.5.0.0/16 # 直接填需要允许的CIDR rules: - host: your-app.example.com http: paths: - path: / pathType: Prefix backend: service: name: your-app-service port: number: 80
关键注意事项
- 一定要正确配置可信代理范围:
proxy-real-ip-cidr和set-real-ip-from必须填你的ELB所在的IP范围,否则恶意请求可以伪造X-Forwarded-For头绕过白名单。你可以在AWS控制台查看ELB的IP,或者用VPC的CIDR(更稳妥)。 - 关于Proxy Protocol:你的场景完全不需要用Proxy Protocol,因为AWS ALB已经通过
X-Forwarded-For传递了真实IP,配置上面的参数就足够了,不用去碰你不熟悉的协议。 - 两种方案的选择:方案一适合需要更复杂规则的场景(比如不同路径用不同白名单),方案二更简洁,适合用原生Ingress字段的场景。
内容的提问来源于stack exchange,提问作者Vitor Falcão




