番外篇:Istio 如何限制訪問來源

緣由

在前陣子,工作上遇到這需求:針對公司內部系統,進行來源訪問限制,亦即是~非公司同仁不能訪問內部系統,提高內部系統資訊安全。 要針對訪問限制,有幾點想法與方向

想法

  • 一個網站,有什麼方式,可以達到來源訪問限制這個目的

    1. 身份認證:可以自行開發身份認證,或者搭配OAuth機制進行網站身份認證。

    2. 限制訪問來源(訪問者IP)。

  • 在 K8s 環境下,您是採用何種 Ingress,每個 Ingress 實現訪問限制的手法不盡相同。

    1. nginx ingress:可以透過nginx配置方式,設定allow方式限制訪問來源。

    2. Istio ingress:Istio Control 訴求面向的實現,有提到IP-based whitelists or blacklists,此功能可以達到限制訪問來源之目的。

  • K8s 原生 Service:

    • 在 service 資源設定中,可以藉由loadBalancerSourceRanges完成限制訪問之目的。除此仍要注意"externalTrafficPolicy":"Local",因為牽涉到Service NAT之原理差異。

做法

先說說,身份認證與限制訪問來源,其實是不相衝突的,可以偕同並行。 兩項都做,豈不是資訊安全的高牆更高。

回到主題,我的環境中使用 Istio 網格服務方案,K8s Service 並不會暴露在外,也沒使用 nginx ingress 這項方案,所以採用 IstioIP-based whitelists or blacklists方式實現目的。

Istio Policy

Istio Policy 功能實現以下目的:

  • Rate limiting to dynamically limit the traffic to a service

    • 說明:例如藍綠部署的應用上,就會運用上這類規則。

  • Denials, whitelists, and blacklists, to restrict access to services

    • 說明:例如我要限制訪問來源,即可套用此規則。

  • Header rewrites and redirects

    • 說明:可針對HTTP 第七層應用上,進行應用上的規則配置。

policy enforcement

如要啟用 Policy 規則,則須先啟用policy enforcement

# 檢查是否啟用
kubectl -n istio-system get cm istio -o jsonpath="{@.data.mesh}" | grep disablePolicyChecks

# 啟用
disablePolicyChecks: false
# 未啟用
disablePolicyChecks: true

# 如未啟用,請設定為啟用狀態
helm template install/kubernetes/helm/istio --namespace=istio-system -x templates/configmap.yaml --set global.disablePolicyChecks=false | kubectl -n istio-system replace -f -

Rule

Istio rule 應用上,主要透過三類 kind 資源,相互搭配應用,各執所司有點複雜.... kind: handlerinstancerule

官網範例:連結

apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
  name: whitelistip
spec:
  compiledAdapter: listchecker
  params:
    # providerUrl: ordinarily black and white lists are maintained
    # externally and fetched asynchronously using the providerUrl.
    overrides: ["10.57.0.0/16"]  # overrides provide a static list
    blacklist: false
    entryType: IP_ADDRESSES
---
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
  name: sourceip
spec:
  compiledTemplate: listentry
  params:
    value: source.ip | ip("0.0.0.0")
---
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: checkip
spec:
  match: source.labels["istio"] == "ingressgateway"
  actions:
  - handler: whitelistip
    instances: [ sourceip ]
---

handler

blacklist: false,顧名思義即為白名單,因為是針對訪問者IP進行檢查與管理,所以entryType須為IP_ADDRESSES

instance

這裡我耗時最久,簡單心得就是: Istio ingressgateway 也是種K8s Service的實作,故其externalTrafficPolicy需設定為local;

Istio instance本質上就是指定什麼樣的attributes(例如http header),進行網格流量的檢查,並設定於value之中,例如範例:透過source.ip方式檢查來源IP是否在白名單。

rule

規則,其就是將上述兩項配置,相互搭配出符合您所需的規則效果。 match部分,則是影響著 Istio 哪些流量需採用此規則。

有關更細節的官方說明,請詳閱此官網連結

Last updated