配置 Gateway 网络拓扑
向目的地的工作负载转发外部客户端属性(IP 地址、证书信息)
许多应用程序需要知道发起源请求的客户端 IP 地址和证书信息才能正常工作。值得注意的是填充了客户端 IP 的日志、验证工具以及安全工具。例如 Web Application Firewalls (WAF),它应用这些信息来运行正确的规则集。
反向代理的主要工作内容是给服务提供客户端属性。为了向目的地的工作负载转发这些客户端属性,代理使用 X-Forwarded-For
(XFF) 和 X-Forwarded-Client-Cert
(XFCC) 头。
如今的网络千差万别,无论网络拓扑结构如何,对这些多样化属性的支持都是必要的。 不管网络使用的是基于云的负载均衡、前置负载均衡、直接暴露在网络上的 Gateway、为许多中间代理服务的 Gateway,还是没有指定其他部署拓扑等,这些信息都是需要保存和转发。
当 Istio 提供一个 Ingress Gateway,鉴于上述多样化架构的复杂性,无法提供合理的默认值,将客户端属性正确转发到目标工作负载。 随着 Istio 多集群部署模式越来越普遍,这个问题需要被越来越重视。
了解关于 X-Forwarded-For
更多信息,参考 IETF 的 RFC。
配置网络拓扑
XFF 和 XFCC 头的配置可以通过 MeshConfig
为所有 Gateway 工作负载进行全局设置,也可以通过使用 Pod 注释给每个 Gateway 配置。例如,在安装或者升级期间,使用 IstioOperator
自定义资源去配置全局设置:
spec:
meshConfig:
defaultConfig:
gatewayTopology:
numTrustedProxies: <VALUE>
forwardClientCertDetails: <ENUM_VALUE>
在您的 Istio Ingress Gateway Pod 的 Spec 通过添加 proxy.istio.io/config
注解可以来设置这两个配置。
...
metadata:
annotations:
"proxy.istio.io/config": '{"gatewayTopology" : { "numTrustedProxies": <VALUE>, "forwardClientCertDetails": <ENUM_VALUE> } }'
配置 X-Forwarded-For 头
应用程序依靠反向代理来转发请求的客户端属性,如 X-Forwarded-For
头。然而由于 Istio 可以部署多样性的网络拓扑,您必须设置 Istio 网关代理上游的可信代理数量 numTrustedProxies
,这样才能正确提取客户端地址。因为它将控制 Ingress Gateway 在 X-Envoy-Eternal-Address
头中填充的值,该值可以被上游服务可靠地用于访问客户的原始 IP 地址。
例如,如果在 Istio Gateway 之前,有一个基于云的负载均衡和一个反向代理,设置 numTrustedProxies
为 2
。
httpbin X-Forwarded-For 示例
运行一下命令去创建一个
topology.yaml
的文件,并且设置numTrustedProxies
为2
,然后安装 Istio:$ cat <<EOF > topology.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: defaultConfig: gatewayTopology: numTrustedProxies: 2 EOF $ istioctl install -f topology.yaml
创建一个
httpbin
命名空间:$ kubectl create namespace httpbin namespace/httpbin created
启用 Sidecar 注入,设置
istio-injection
标签为enabled
:$ kubectl label --overwrite namespace httpbin istio-injection=enabled namespace/httpbin labeled
在
httpbin
命名空间部署httpbin
:$ kubectl apply -n httpbin -f samples/httpbin/httpbin.yaml
部署一个
httpbin
相关的 Gateway:$ kubectl apply -n httpbin -f samples/httpbin/httpbin-gateway.yaml
基于您的 Istio Ingress Gateway 设置一个本地环境变量
GATEWAY_URL
:$ export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
运行下面的
curl
命令,模拟在X-Forwarded-For
头中包含代理地址的请求:$ curl -H 'X-Forwarded-For: 56.5.6.7, 72.9.5.6, 98.1.2.3' $GATEWAY_URL/get?show_env=true { "args": { "show_env": "true" }, "headers": { ... "X-Envoy-External-Address": "72.9.5.6", ... "X-Forwarded-For": "56.5.6.7, 72.9.5.6, 98.1.2.3, <YOUR GATEWAY IP>", ... }, ... }
上面的输出显示了 httpbin
工作负载收到的请求头。当 Istio Gateway 收到这个请求时,它将X-Envoy-External-Address
头设置为您 curl 命令中 X-Forwarded-For
头中的第二个到最后一个(numTrustedProxies: 2
)地址。此外,Gateway 在将其转发到 httpbin
工作负载之前,会将自己的 IP 附加到 X-Forwarded-For
头中。
配置 X-Forwarded-Client-Cert 头
从 Envoy 文档 参考 XFCC:
配置如何处理 XFCC 头文件,需要在 IstioOperator
中设置 forwardClientCertDetails
:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
gatewayTopology:
forwardClientCertDetails: <ENUM_VALUE>
其中ENUM_VALUE
可以是以下类型:
ENUM_VALUE | |
---|---|
UNDEFINED | 没有设置字段。 |
SANITIZE | 不要向下一跳地址发送 XFCC 头。这是 Gateway 的默认值。 |
FORWARD_ONLY | 当客户端连接为mTLS(Mutual TLS)时,在请求中转发 XFCC 头。 |
APPEND_FORWARD | 当客户端连接为 mTLS 时,将客户端证书信息附加到请求的 XFCC头 中并转发。 |
SANITIZE_SET | 当客户端连接为 mTLS 时,用客户端证书信息重置 XFCC 头,并将其发送到下一跳地址。 |
ALWAYS_FORWARD_ONLY | 无论客户端连接是否为 mTLS,总是在请求中转发 XFCC 头。 |
参考 Envoy 文档,了解并使用此功能的示例。
PROXY 协议
PROXY 协议 允许在不依赖7层协议的情况下,在多个代理之间交换和保存客户端属性。
如果外部负载均衡器使用 PROXY 协议,Istio Gateway 也必须配置接受 PROXY 协议。启用该功能需要在 Gateway 工作负载上使用 EnvoyFilter
添加 Envoy PROXY 协议过滤器。示例:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: proxy-protocol
namespace: istio-system
spec:
configPatches:
- applyTo: LISTENER
patch:
operation: MERGE
value:
listener_filters:
- name: envoy.listener.proxy_protocol
- name: envoy.listener.tls_inspector
workloadSelector:
labels:
istio: ingressgateway
客户端 IP 从 PROXY 协议中获取,并在 X-Forwarded-For
和 X-Envoy-External-Address
头中设置(或附加)。当 PROXY 协议与 gatewayTopology
配置一起使用时,确定可信客户地址时会优先使用 numTrustedProxies
和接收到的 X-Forwarded-For
头。