在HTTP請求頭中獲取客戶端真實IP
為了對ASM的入口網(wǎng)關進行訪問保護,需要獲取客戶端真實IP,以便使用授權策略設置訪問入口網(wǎng)關的IP黑名單和白名單。本文介紹如何在HTTP請求頭中獲取客戶端真實IP。
前提條件
已為命名空間注入Sidecar。具體操作,請參見啟用自動注入。
背景信息
通常情況下,應用程序依靠反向代理來轉發(fā)請求中的客戶端屬性,例如X-Forwarded-For標頭。但是由于Istio可以部署多種網(wǎng)絡拓撲,除了直接使用負載均衡器CLB的公網(wǎng)地址訪問之外,也可能會在Web應用程序防火墻(WAF)接入入口網(wǎng)關地址,或者使用其他的未指定的部署拓撲來訪問入口網(wǎng)關地址。在支持各種部署架構的情況下,服務網(wǎng)格ASM無法提供一個固定的默認值,將客戶端屬性正確轉發(fā)到目標工作負載,也就無法直接通過X-Forwarded-For獲取客戶端真實IP。
為了解決上述問題,您需要在ASM網(wǎng)關中將numTrustedProxies參數(shù)的值,配置為部署在網(wǎng)關代理前面的可受信的代理數(shù)量,以便正確獲取客戶端地址。控制入口網(wǎng)關在X-Envoy-External-Address標頭中填充的值,以便上游服務使用該值來訪問客戶端的原始IP地址。
操作步驟
部署示例應用。
通過kubectl管理集群和應用。具體操作,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
部署httpbin應用。
使用以下內(nèi)容創(chuàng)建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: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/httpbin:0.1.0 imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80
執(zhí)行以下命令,部署httpbin應用。
kubectl apply -f httpbin.yaml
創(chuàng)建ASM網(wǎng)關。
登錄ASM控制臺,在左側導航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 。
在入口網(wǎng)關頁面,單擊創(chuàng)建,配置網(wǎng)關的基本信息。
負載均衡CLB類型選擇公網(wǎng)訪問,其他按需配置即可。關于配置項的更多信息,請參見創(chuàng)建入口網(wǎng)關服務。
單擊高級選項,設置外部流量策略為Local,然后單擊創(chuàng)建。
創(chuàng)建網(wǎng)關規(guī)則和虛擬服務。
通過API方式管理ASM實例。具體操作,請參見通過控制面kubectl訪問Istio資源。
創(chuàng)建網(wǎng)關規(guī)則。
使用以下內(nèi)容,創(chuàng)建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: - "*"
執(zhí)行以下命令,創(chuàng)建網(wǎng)關規(guī)則。
kubectl apply -f httpbin-gateway.yaml
創(chuàng)建虛擬服務。
使用以下內(nèi)容,創(chuàng)建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
執(zhí)行以下命令,創(chuàng)建虛擬服務。
kubectl apply -f httpbin-virtualservice.yaml
獲取httpbin應用的80端口的入口網(wǎng)關地址。具體操作,請參見創(chuàng)建入口網(wǎng)關服務。
為ASM網(wǎng)關添加numTrustedProxies參數(shù)。
登錄ASM控制臺,在左側導航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 。
在入口網(wǎng)關頁面的目標網(wǎng)關右側,單擊查看YAML。
在編輯對話框的spec參數(shù)下,添加以下內(nèi)容,然后單擊確定。
podAnnotations: proxy.istio.io/config: '{"gatewayTopology" : { "numTrustedProxies": 2 } }'
根據(jù)實際的拓撲設置numTrustedProxies為部署在網(wǎng)關代理前面的可受信的代理數(shù)量。如果設置numTrustedProxies為一個大于零的值N,則可信客戶端地址為X-Forwarded-For右側起的第N+1個地址。
執(zhí)行以下命令,訪問httpbin應用,獲取客戶端真實IP。
curl http://{入口網(wǎng)關地址}/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。