为了对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。