全部產品
Search
文件中心

Alibaba Cloud Service Mesh:限制特定IP訪問網格內應用

更新時間:Jun 30, 2024

本文介紹如何限制特定IP訪問網格內應用。

前提條件

使用說明

本文網關的externalTrafficPolicy均設定為LocalexternalTrafficPolicy設定為Cluster無法保留源IP。

情境一:ASM網關之前不存在7層代理

執行以下命令,直接存取httpbin。

curl 47.111.XXX.XX:80/ -I

展開查看網關側產生的日誌

{
    "authority_for": "47.111.XXX.XX",
    "bytes_received": "0",
    "bytes_sent": "0",
    "downstream_local_address": "10.0.70.17:80",
    "downstream_remote_address": "106.XX.XX.1:58656",
    "duration": "2",
    "istio_policy_status": "-",
    "method": "HEAD",
    "path": "/",
    "protocol": "HTTP/1.1",
    "request_id": "b1aa0770-4f64-4798-894a-4a04a0ba****",
    "requested_server_name": "-",
    "response_code": "200",
    "response_flags": "-",
    "route_name": "httpbin",
    "start_time": "2023-08-31T06:42:47.380Z",
    "trace_id": "-",
    "upstream_cluster": "outbound|8000||httpbin.default.svc.cluster.local",
    "upstream_host": "10.0.70.85:80",
    "upstream_local_address": "10.0.70.17:56110",
    "upstream_response_time": "2",
    "upstream_service_time": "2",
    "upstream_transport_failure_reason": "-",
    "user_agent": "curl/7.88.1",
    "x_forwarded_for": "106.11.XX.X"
}

用戶端實際IP為106.11.XX.X。從網關日誌可以看到downstream_remote_addressx_forwarded_for中的值都正確。此時,在網關上配置ipBlocksremoteIpBlocks都可以生效。

展開查看Sidecar側的訪問日誌

{
    "authority_for": "47.111.XXX.XX",
    "bytes_received": "0",
    "bytes_sent": "0",
    "downstream_local_address": "10.0.70.91:80",
    "downstream_remote_address": "106.11.XX.X:0",
    "duration": "1",
    "istio_policy_status": "-",
    "method": "HEAD",
    "path": "/",
    "protocol": "HTTP/1.1",
    "request_id": "20c94846-3e12-458a-b7d5-88ac867f****",
    "requested_server_name": "outbound_.8000_._.httpbin.default.svc.cluster.local",
    "response_code": "200",
    "response_flags": "-",
    "route_name": "default",
    "start_time": "2023-08-31T10:06:33.809Z",
    "trace_id": "-",
    "upstream_cluster": "inbound|80||",
    "upstream_host": "10.0.70.91:80",
    "upstream_local_address": "127.0.X.X:43247",
    "upstream_response_time": "1",
    "upstream_service_time": "1",
    "upstream_transport_failure_reason": "-",
    "user_agent": "curl/7.88.1",
    "x_forwarded_for": "106.11.XX.X"
}

從Sidecar側的訪問日誌可以看到x_forwarded_for中的值依然為用戶端真實IP。downstream_remote_address也是用戶端真實IP,但是丟失了連接埠資訊,顯示為0

樣本一:網關側配置黑白名單

測試ipBlocks

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    您可以使用ASM安全性原則或網關的黑白名單簡化配置。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test
      namespace: istio-system
    spec:
      action: DENY
      rules:
        - from:
            - source:
                ipBlocks:
                  - 106.11.XX.X
      selector:
        matchLabels:
          istio: ingressgateway
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.175.XX:XX/ -I

    預期輸出:

    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Thu, 31 Aug 2023 06:56:00 GMT
    server: istio-envoy

測試remoteIpBlocks

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    您可以使用ASM安全性原則或網關的黑白名單簡化配置。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test
      namespace: istio-system
    spec:
      action: DENY
      rules:
        - from:
            - source:
                remoteIpBlocks:
                  - 106.11.XX.X
      selector:
        matchLabels:
          istio: ingressgateway
    
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.175.XX:XX/ -I

    預期輸出:

    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Thu, 31 Aug 2023 09:59:02 GMT
    server: istio-envoy

樣本二:Sidecar側配置黑白名單

測試ipBlocks

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test
      namespace: default
    spec:
      action: DENY
      rules:
        - from:
            - source:
                ipBlocks:
                  - 106.11.XX.X
      selector:
        matchLabels:
          app: httpbin
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.175.XX:XX/ -I

    預期輸出:

    HTTP/1.1 200 OK
    server: istio-envoy
    date: Thu, 31 Aug 2023 10:14:01 GMT
    content-type: text/html; charset=utf-8
    content-length: 9593
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 2

    從Sidecar側的訪問日誌可以看到,downstream_remote_address是用戶端IP,但是沒有被攔截。

    downstream_remote_address並不完全等於ipBlocks中限制的欄位。ipBlocks限制“和當前代理直接建立TCP串連的用戶端IP”,所以真實發送過來的源IP是網關的Pod IP。downstream_remote_address是一個較為靈活的欄位,並不總是下遊的物理IP。

    downstream_remote_address表示下遊串連的遠端地址。如果該地址是一個IP地址,則它包含IP和連接埠。它不是遠端的真實物理地址,該地址可能來自於ProxyProtocol過濾器或x_forwarded_for要求標頭。

    您可以測試將ipBlocks中的地址換成網關的Pod IP,配置後將無法訪問httpbin。

測試remoteIpBlocks

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test
      namespace: default
    spec:
      action: DENY
      rules:
        - from:
            - source:
                remoteIpBlocks:
                  - 106.11.XX.X
      selector:
        matchLabels:
          app: httpbin
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.XXX.XX:80/ -I

    預期輸出:

    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Thu, 31 Aug 2023 11:06:42 GMT
    server: istio-envoy
    x-envoy-upstream-service-time: 0

    remoteIpBlocks配置生效,因為x_forwarded_for中的值正常。

情境二:ASM網關之前存在7層代理

此情境下,ASM網關收到的請求中,x_forwarded_for要求標頭中應有預設值(由網關之前的7層代理提添加)。

展開查看網關側日誌

{
    "authority_for": "47.111.XXX.XX",
    "bytes_received": "0",
    "bytes_sent": "0",
    "downstream_local_address": "10.0.70.17:80",
    "downstream_remote_address": "106.11.XX.X:62232",
    "duration": "4",
    "istio_policy_status": "-",
    "method": "HEAD",
    "path": "/",
    "protocol": "HTTP/1.1",
    "request_id": "4f8ee609-1479-4f75-ba9d-4fa6d646****",
    "requested_server_name": "-",
    "response_code": "200",
    "response_flags": "-",
    "route_name": "httpbin",
    "start_time": "2023-08-31T11:25:11.376Z",
    "trace_id": "-",
    "upstream_cluster": "outbound|8000||httpbin.default.svc.cluster.local",
    "upstream_host": "10.0.70.91:80",
    "upstream_local_address": "10.0.70.17:42646",
    "upstream_response_time": "4",
    "upstream_service_time": "4",
    "upstream_transport_failure_reason": "-",
    "user_agent": "curl/7.88.1",
    "x_forwarded_for": "56.5.X.X, 72.9.X.X, 98.1.X.X,106.11.XX.X"
}

到達網關之前的x_forwarded_for要求標頭應為56.5.X.X, 72.9.X.X, 98.1.X.X,最後的一個IP(106.11.XX.X)由ASM網關添加。downstream_remote_address表示與網關直接相連的對端IP(此時是真實的物理IP,所以是一個有效連接埠)。

展開查看Sidecar側日誌

{
    "authority_for": "47.111.XXX.XX",
    "bytes_received": "0",
    "bytes_sent": "0",
    "downstream_local_address": "10.0.70.91:80",
    "downstream_remote_address": "106.11.XX.X:0",
    "duration": "1",
    "istio_policy_status": "-",
    "method": "HEAD",
    "path": "/",
    "protocol": "HTTP/1.1",
    "request_id": "4f8ee609-1479-4f75-ba9d-4fa6d646****",
    "requested_server_name": "outbound_.8000_._.httpbin.default.svc.cluster.local",
    "response_code": "200",
    "response_flags": "-",
    "route_name": "default",
    "start_time": "2023-08-31T11:25:11.378Z",
    "trace_id": "-",
    "upstream_cluster": "inbound|80||",
    "upstream_host": "10.0.70.91:80",
    "upstream_local_address": "127.0.X.X:34607",
    "upstream_response_time": "1",
    "upstream_service_time": "1",
    "upstream_transport_failure_reason": "-",
    "user_agent": "curl/7.88.1",
    "x_forwarded_for": "56.5.X.X, 72.9.X.X, 98.1.X.X,106.11.XX.X"
}

從Sidecar的日誌可以看到,x_forwarded_for要求標頭和網關側相同。downstream_remote_address此時並不是真實的物理地址,而是來自於x_forwarded_for要求標頭的最後一個值(由於x_forwarded_for中只有IP,所以此處連接埠為0)。

下文不再測試ipBlocks欄位(該欄位表示對端真實物理IP),僅測試remoteIpBlocks欄位。這種情況下,需要將x_forwarded_for看作一個數組,此時限制“誰可以訪問ASM網關”,即限制上述日誌中x_forwarded_for的最後一個元素。

樣本一:配置remoteIpBlocks為x_forwarded_for中的最後一個地址

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test-ap-wg-gateway-test-istio-system-gateway-ingressgateway
      namespace: istio-system
    spec:
      action: DENY
      rules:
        - from:
            - source:
                remoteIpBlocks:
                  - 106.11.XX.X
      selector:
        matchLabels:
          istio: ingressgateway
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.175.XX:XX/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I

    預期輸出:

    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Thu, 31 Aug 2023 11:50:36 GMT
    server: istio-envoy

    預期輸出表明成功限制x_forwarded_for中的最後一個地址。

樣本二:設定網關的numTrustedProxies為2

  1. 在入口網關YAML的spec欄位中添加如下配置。關於如何編輯入口網關,請參見通過ASM控制台管理入口網關

    podAnnotations:
        proxy.istio.io/config: '{"gatewayTopology" : { "numTrustedProxies": 2 } }'
    說明

    該配置會導致網關重啟。

  2. 網關重啟後,執行以下命令,訪問httpbin。

    curl 47.111.XXX.XX:80/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I

    預期輸出:

    HTTP/1.1 200 OK
    server: istio-envoy
    date: Thu, 31 Aug 2023 12:10:15 GMT
    content-type: text/html; charset=utf-8
    content-length: 9593
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 2

    預期輸出表明訪問成功,numTrustedProxies影響了remoteIpBlocks中的判斷結果。

    numTrustedProxies設定為2,表示網關會認為最靠近ASM網關的2個代理是可信的,第三近的代理不可信。因此,remoteIpBlocks限制第三近的代理IP。numTrustedProxies在不配置的情況下,預設值為0。

樣本三:授權策略中限制網關日誌x_forwarded_for的倒數第三個地址

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test-ap-wg-gateway-test-istio-system-gateway-ingressgateway
      namespace: istio-system
    spec:
      action: DENY
      rules:
        - from:
            - source:
                remoteIpBlocks:
                  - 72.9.X.X
      selector:
        matchLabels:
          istio: ingressgateway
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.XXX.XX:80/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I

    預期輸出:

    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Thu, 31 Aug 2023 12:38:09 GMT
    server: istio-envoy

    預期輸出表明成功限制x_forwarded_for的倒數第三個地址。

樣本四:變更上述授權策略的生效範圍為httpbin應用

  1. 使用以下內容,建立授權策略gateway-test.yaml。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: gateway-test
      namespace: default
    spec:
      action: DENY
      rules:
        - from:
            - source:
                remoteIpBlocks:
                  - 72.9.X.X
      selector:
        matchLabels:
          app: httpbin
  2. 執行以下命令,部署授權策略。

    kubectl apply -f gateway-test.yaml
  3. 執行以下命令,訪問httpbin。

    curl 47.111.XXX.XX:80/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I

    預期輸出:

    HTTP/1.1 200 OK
    server: istio-envoy
    date: Thu, 31 Aug 2023 12:39:36 GMT
    content-type: text/html; charset=utf-8
    content-length: 9593
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 6

    預期輸出表明訪問成功,授權策略規則失效。因為上述numTrustedProxies是為網關配置的,Sidecar的numTrustedProxies預設值還是0,它會校正自己收到的x_forwarded_for要求標頭的最後一個值,因此沒有成功拒絕當前請求。

    您可以修改該授權策略中的remoteIpBlocks為Sidecar日誌中x_forwarded_for的最後一個IP,即可看到訪問被拒絕。