为了对ASM的入口网关进行访问保护,需要获取客户端真实IP,以便使用授权策略设置访问入口网关的IP黑名单和白名单。本文介绍如何在HTTP请求头中获取客户端真实IP。
前提条件
- 已为命名空间注入Sidecar。具体操作,请参见启用自动注入。 
背景信息
通常情况下,应用程序依靠反向代理来转发请求中的客户端属性,例如X-Forwarded-For标头。但是由于Istio可以部署多种网络拓扑,除了直接使用负载均衡器CLB的公网地址访问之外,也可能会在Web应用程序防火墙(WAF)接入入口网关地址,或者使用其他的未指定的部署拓扑来访问入口网关地址。在支持各种部署架构的情况下,服务网格ASM无法提供一个固定的默认值,将客户端属性正确转发到目标工作负载,也就无法直接通过X-Forwarded-For获取客户端真实IP。
为了解决上述问题,您需要在ASM网关中将numTrustedProxies参数的值,配置为部署在网关代理前面的可受信的代理数量,以便正确获取客户端地址。控制入口网关在X-Envoy-External-Address标头中填充的值,以便上游服务使用该值来访问客户端的原始IP地址。
操作步骤
- 部署示例应用。 - 通过kubectl管理集群和应用。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。 
- 部署httpbin应用。 - 使用以下内容创建httpbin.yaml文件。 
- 执行以下命令,部署httpbin应用。 - kubectl apply -f httpbin.yaml
 
 
- 创建ASM网关。 
- 创建网关规则和虚拟服务。 - 通过API方式管理ASM实例。具体操作,请参见通过控制面kubectl访问Istio资源。 
- 创建网关规则。 - 使用以下内容,创建httpbin-gateway.yaml文件。 - apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"
- 执行以下命令,创建网关规则。 - kubectl apply -f httpbin-gateway.yaml
 
- 创建虚拟服务。 - 使用以下内容,创建httpbin-virtualservice.yaml文件。 - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "*" gateways: - httpbin-gateway http: - route: - destination: host: httpbin port: number: 8000
- 执行以下命令,创建虚拟服务。 - kubectl apply -f httpbin-virtualservice.yaml
 
 
- 获取httpbin应用的80端口的入口网关地址。具体操作,请参见创建入口网关服务。 
- 为ASM网关添加numTrustedProxies参数。 - 登录ASM控制台,在左侧导航栏,选择。 
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择。 
- 在入口网关页面的目标网关右侧,单击查看YAML。 
- 在编辑对话框的spec参数下,添加以下内容,然后单击确定。 - podAnnotations: proxy.istio.io/config: '{"gatewayTopology" : { "numTrustedProxies": 2 } }'- 根据实际的拓扑设置numTrustedProxies为部署在网关代理前面的可受信的代理数量。如果设置numTrustedProxies为一个大于零的值N,则可信客户端地址为X-Forwarded-For右侧起的第N+1个地址。 
 
- 执行以下命令,访问httpbin应用,获取客户端真实IP。 - curl http://{入口网关地址}/get?show_env=true- 预期输出: - { "args": { "show_env": "true" }, "headers": { "Accept": "*/*", .... "X-Envoy-Attempt-Count": "1", "X-Envoy-External-Address": "106.11.**.**", .... }, .... }- X-Envoy-External-Address的值即为客户端真实IP。