Azure Kubernetes部署Spring Cloud Gateway无法获取真实客户端IP
解决Azure Kubernetes中Spring Cloud Gateway获取真实客户端IP的问题
问题根源
你看到的10.x.x.x是Azure Kubernetes节点或LoadBalancer的内部IP,原因有两点:
- 默认情况下,Kubernetes LoadBalancer Service会启用SNAT(源地址转换),导致Pod收到的请求源IP被替换为集群内部IP
- Spring Cloud Gateway的
XForwardedRemoteAddressResolver信任代理层数设置不正确,无法正确解析真实客户端IP
解决方案步骤
1. 修改Kubernetes Service配置,保留客户端源IP
更新你的gateway-service Service,添加externalTrafficPolicy: Local配置,这会让Azure LoadBalancer直接将请求转发到Pod所在节点,避免SNAT,同时保留客户端IP:
apiVersion: v1 kind: Service metadata: name: gateway-service spec: type: LoadBalancer externalTrafficPolicy: Local # 关键配置:禁用SNAT,保留客户端源IP selector: app: api-gateway ports: - port: 80 targetPort: 8080
2. 配置Spring Cloud Gateway信任代理并正确解析X-Forwarded-For头
首先,在Spring Cloud Gateway的配置文件(如application.yml)中添加以下配置,启用对X-Forwarded系列头的支持,并信任Azure集群的内部IP段:
spring: cloud: gateway: x-forwarded: enabled: true for: enabled: true trusted-ips: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 # Azure K8s内部IP段,可按需调整
然后,调整ClientIpFilter代码中的代理信任层数。由于请求经过了Azure LoadBalancer和K8s节点两层代理,将maxTrustedIndex设置为2:
@Component public class ClientIpFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 设置信任2层代理,对应Azure LB和K8s节点 var resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(2); var clientAddress = resolver.resolve(exchange); if (clientAddress != null) { String realClientIp = clientAddress.getAddress().getHostAddress(); // 可将真实IP存入exchange属性,供后续业务逻辑使用 exchange.getAttributes().put("realClientIp", realClientIp); } return chain.filter(exchange); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } }
3. 验证配置
重新部署Service和Gateway Pod后,发送请求测试,此时clientAddress应返回真实的客户端公网IP。
补充说明
externalTrafficPolicy: Local会让只有Pod所在的节点接收LoadBalancer流量,若Deployment有多副本,需确保各节点都有Pod运行,避免流量丢失trusted-ips配置可限制信任的代理IP段,提升安全性,可根据Azure集群实际内部IP范围调整
内容的提问来源于stack exchange,提问作者unuser
相关产品推荐
相关产品推荐

