为了对ASM的入口网关进行访问保护,需要获取客户端真实IP,以便使用授权策略设置访问入口网关的IP黑名单和白名单。本文介绍如何在HTTP请求头中获取客户端真实IP。
背景信息
通常情况下,应用程序依靠反向代理来转发请求中的客户端属性,例如X-Forward-For标头。但是由于Istio可以部署多种网络拓扑,除了直接使用负载均衡器SLB的公网地址访问之外,也可能会在Web应用程序防火墙(WAF)接入入口网关地址,或者使用其他的未指定的部署拓扑来访问入口网关地址。在支持各种部署架构的情况下,服务网格ASM无法提供一个固定的默认值,将客户端属性正确转发到目标工作负载,也就无法直接通过X-Forwarded-For获取客户端真实IP。
为了解决上述问题,您需要在ASM网关中将numTrustedProxies参数的值,配置为部署在网关代理前面的可受信的代理数量,以便正确获取客户端地址。控制入口网关在X-Envoy-External-Address标头中填充的值,以便上游服务使用该值来访问客户端的原始IP地址。
操作步骤
- 部署示例应用。
- 通过kubectl管理集群和应用。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
- 部署httpbin应用。
- 使用以下内容创建httpbin.yaml文件。
# httpbin service
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
- 执行以下命令,部署httpbin应用。
kubectl apply -f httpbin.yaml
- 创建ASM网关。
- 登录ASM控制台,在左侧导航栏,选择。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择。
- 在入口网关页面,单击创建,配置网关的基本信息。
重要配置项说明如下,其他配置项保持默认即可。关于配置项的更多信息,请参见
创建入口网关服务。
配置项 | 说明 |
---|
名称 | 自定义网关的名称。 |
部署集群 | 选择网关部署的集群。 |
负载均衡类型 | 选择公网访问。 |
新建负载均衡 | 选择负载均衡,可选:- 使用已有负载均衡:从已有负载均衡列表中选择。
- 新建负载均衡:单击新建负载均衡,从下拉列表中选择所需的负载均衡规格。
|
端口映射 | 单击添加端口,在新增端口行中,选择协议,输入服务端口。 |
- 单击高级选项,设置外部流量策略为Local,然后单击创建。
- 创建网关规则和虚拟服务。
- 通过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端口的入口网关地址。具体操作,请参见创建入口网关服务。
- 在Web应用程序防火墙,接入步骤4获取的入口网关的地址。具体操作,请参见使用教程。
- 为ASM网关添加numTrustedProxies参数。
- 登录ASM控制台,在左侧导航栏,选择。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择。
- 在入口网关页面的目标网关右侧,单击查看YAML。
- 在编辑对话框的spec参数下,添加以下内容,然后单击确定。
podAnnotations:
proxy.istio.io/config: '{"gatewayTopology" : { "numTrustedProxies": 2 } }'
根据实际的拓扑设置numTrustedProxies为部署在网关代理前面的可受信的代理数量。如果设置numTrustedProxies为一个大于零的值N,则可信客户端地址为X-Forward-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。