在容器化環境中,網路安全是保障系統穩定性和資料安全的關鍵環節。Kubernetes作為主流的容器協調平台,其網路安全架構需要特別關注。玄貓在多年實踐中發現,許多團隊往往專注於應用程式安全,而忽略了底層網路通訊的安全性,這正是許多安全漏洞的溫床。
Pod到節點的通訊風險
在Kubernetes預設設定下,Pod可以查詢它們所執行的工作節點(Node)以及佈署環境的相關訊息。這種設計雖然便於監控和診斷,但也帶來了潛在的安全風險。
當CNI(Container Network Interface)允許Pod存取節點時,若沒有適當的防護措施,攻擊者可能利用這一通道存取節點資源,進而取得雲端環境的敏感資料或API伺服器。這種情況下,整個叢集的安全邊界就被打破了。
雲端環境的防護策略
各大雲端服務提供商都提供了特定的解決方案來緩解這一風險:
- Google提供了受保護的GKE節點(Shielded GKE Nodes)
- Amazon EKS建議限制對執行個體中繼資料的存取
- GKE提供了保護叢集中繼資料的方法
玄貓在實施雲端安全策略時,經常採用的一個方法是為工作節點設定嚴格的網路政策,限制Pod只能存取其正常執行所需的節點資源。這種「最小許可權」原則在實踐中能有效降低風險。
除了雲提供商的解決方案,也可以考慮使用商業產品如Nirmata的虛擬叢集和工作負載政策來加強安全邊界。
叢集外部流量管理
Kubernetes提供了多種機制來允許Pod與叢集外部端點通訊,其中最常用的是Ingress資源。
Ingress控制器的選擇
Ingress允許第7層(HTTP)路由,而對於第3/4層路由則需要使用其他方法。要使用Ingress資源,需要選擇一個Ingress控制器。市面上有許多開放原始碼選擇:
- Emissary-ingress
- Contour
- HAProxy Ingress
- NGINX Ingress Controller
- Traefik
雲端服務提供商通常也提供自己的解決方案,這些解決方案與其代管的負載平衡服務整合。
在選擇Ingress控制器時,玄貓建議考慮以下因素:效能需求、功能豐富度、社群活躍度以及團隊的熟悉程度。例如,對於需要高度自定義路由規則的場景,Traefik可能是更好的選擇;而對於追求穩定性和廣泛支援的團隊,NGINX Ingress Controller可能更合適。
傳輸加密與安全
現今,傳輸層加密(TLS)幾乎已成為標準設定,大多數Ingress解決方案都內建支援。此外,也可以考慮使用服務網格來保護南北向流量。
在應用層面,可以考慮使用Web應用防火牆(WAF),這類別服務由大多數雲提供商提供,也可以使用獨立產品如Wallarm。
越來越多的實踐者分享他們在這方面的經驗,可以關注相關部落格文章和CNCF網路研討會。例如「Shaping Chick-fil-A One Traffic in a Multi-Region Active-Active Architecture」。
ARP欺騙與防護
地址解析協定(ARP)是一種用於將IP網路地址對映到硬體(MAC)地址的鏈路層協定。Liz Rice在KubeCon NA 2019的演講「CAP_NET_RAW and ARP Spoofing in Your Cluster: It’s Going Downhill From Here」中展示了預設設定如何允許開啟原始網路通訊端,以及這如何導致安全問題。
ARP攻擊的風險
這種攻擊涉及使用ARP和DNS欺騙受害Pod存取假URL,這是由於Kubernetes處理本地FQDN的方式,與需要Pod具有CAP_NET_RAW能力。
更多詳情可參見Aqua Security的部落格文章「DNS Spoofing on Kubernetes Clusters」。
防禦措施
好訊息是,有多種防禦措施可以緩解根據ARP的攻擊:
- 使用Pod安全策略(PSP)來移除CAP_NET_RAW能力
- 使用通用策略引擎如Open Policy Agent/Gatekeeper或使用Kyverno轉換PSP
- 在第3層使用Calico或Cilium等工具
玄貓在實踐中發現,移除不必要的容器能力是提高安全性的簡單有效方法。特別是CAP_NET_RAW這類別高風險能力,在絕大多數應用場景中都不是必需的。
要檢測是否受到影響,可以使用kube-hunter等工具進行掃描和評估。
安全上下文與工作負載保護
安全上下文的重要性
預設情況下,工作負載可以升級到其執行的工作節點的網路介面。例如,執行特權容器時,攻擊者可以使用核心模組逃逸容器。此外,正如微軟Azure團隊在「Threat matrix for Kubernetes」部落格文章中指出:
攻擊者若能存取主機網路(例如透過在受損容器上執行程式碼),可以向Kubelet API傳送API請求。具體來說,查詢https://[NODE IP]:10255/pods/
可以取得節點上執行的pod訊息;https://[NODE IP]:10255/spec/
可以取得關於節點本身的訊息,如CPU和記憶體消耗。
防護策略
為避免這些情況,可以應用Pod安全策略(PSP)。例如,基準/預設策略定義了以下限制:
- 禁止分享主機名稱空間:
- spec.hostNetwork
- spec.hostPID
- spec.hostIPC
- 禁止特權Pod(停用大多數安全機制):
- spec.containers[*].securityContext.privileged
- spec.initContainers[*].securityContext.privileged
- 禁止或至少限制HostPorts到已知列表:
- spec.containers[].ports[].hostPort
- spec.initContainers[].ports[].hostPort
除此之外,還可以使用商業產品,如Palo Alto Networks Prisma Cloud(前身為Twistlock),來加強工作節點的安全性。
玄貓在實施容器安全策略時,通常建議從最嚴格的安全設定開始,然後根據應用需求逐步放寬限制,而不是從寬鬆設定開始再逐步加強。這種「安全優先」的方法能有效防止設定漏洞。
工作負載身分識別
預設情況下,Kubernetes不會為服務分配身分識別。SPIFFE/SPIRE可用於管理工作負載身分並啟用mTLS。
SPIFFE與SVID
SPIFFE(Secure Production Identity Framework for Everyone)是一組用於安全識別工作負載的規範。它提供了一個框架,透過API定義短期加密身分檔案—稱為SPIFFE可驗證身分檔案(SVID)—來動態地為跨環境的服務發放身分識別。
工作負載可以在與其他工作負載進行身分驗證時使用這些SVID。例如,SVID可用於建立TLS連線或驗證JWT令牌。
玄貓在設計微服務架構時,工作負載身分識別是我最關注的安全環節之一。沒有明確的身分識別機制,微服務之間的互信就建立在脆弱的網路隔離上,這在現代雲原生環境中是遠不夠的。
傳輸加密的必要性
對於受監管行業的工作負載,即任何需要符合(政府發布的)法規的應用,傳輸加密通常是要求之一。例如,如果你是銀行擁有符合支付卡行業資料安全標準(PCI DSS)的應用,或者是醫療提供者擁有符合健康保險可攜性和責任法案(HIPAA)的應用,你需要確保容器化微服務之間的通訊受到保護,防止嗅探和中間人攻擊。
TLS協定與實作
如今,通常使用傳輸層安全(TLS)協定(在RFC 8446和較早的IETF檔案中定義)來加密傳輸中的流量。它使用非對稱加密在工作階段開始時(「握手」)協商分享金鑰,然後使用對稱加密來加密工作負載資料。這種設定是效能與安全之間的良好平衡。
雖然控制平面元件如API伺服器、etcd或kubelet可以依賴內建的PKI基礎設施,為證書提供API和最佳實踐,但對於工作負載來說,情況遺憾地並非如此。
這段技術內容解釋了TLS協定的工作原理,它使用兩種加密方式:初始的「握手」階段用非對稱加密(計算成本高但更安全)來安全地交換金鑰,之後的資料傳輸使用對稱加密(更高效)。這種雙重機制在安全性和效能之間取得了平衡。值得注意的是,雖然Kubernetes控制平面元件內建了PKI支援,但使用者工作負載需要自行實作TLS加密。
提示:你可以使用openssl檢視API伺服器的主機名和編碼到其TLS證書中的任何IP。
預設情況下,Pod之間以及Pod與外部世界之間的流量是不加密的。為了緩解這一問題,可以啟用工作負載傳輸加密,例如:
- 使用Calico
- 使用Wireguard 虛擬私人網路
- 使用Cilium(支援Wireguard和IPsec)
另一個選擇是服務網格,它不僅提供加密,還能提供工作負載身分識別。
網路安全威脅模型
在網路安全空間中,我們需要考慮什麼樣的威脅模型?什麼是我們對攻擊者可能對工作負載和基礎設施做什麼的假設?
以下觀察應該能讓你瞭解潛在的威脅模型。我們用2018-2020年間的一些過去攻擊案例來說明這些情景:
常見攻擊向量
使用前門入侵:透過Ingress控制器或負載平衡器,然後進行橫向移動或執行拒絕服務攻擊,如CVE-2020-15127中觀察到的
開發者存取路徑:利用
kubectl cp
(CVE-2019-11249)或Minikube等開發環境,如CVE-2018-1002103中所見特權容器濫用:啟動具有主機網路存取許可權或不必要能力的Pod
橫向移動:利用已被入侵的工作負載連線到另一個工作負載
網路掃描:對所有CNI外掛進行連線埠掃描,並進一步使用這些訊息識別漏洞,例如CVE-2019-9946
控制平面攻擊:攻擊API伺服器、etcd、kubelet或kube-proxy等控制平面元件,例如CVE-2020-8558、CVE-2019-11248、CVE-2019-11247和CVE-2018-1002105
伺服器端請求偽造(SSRF):針對託管環境,如雲提供商的VM
中間人攻擊:如在IPv6路由環境中看到的,另見CVE-2020-10749
玄貓在安全評估中發現,大多陣列織對第1、5、6類別攻擊有一定的防範意識,但對於2、3、4、7、8類別攻擊的防護往往不足。特別是橫向移動和SSRF這類別攻擊,在微服務架構中尤為危險,因為它們可以繞過外部防禦機制,直接在內部網路中擴散。
網路安全加固策略
根據上述威脅模型,玄貓建議採取以下網路安全加固策略:
基礎防護措施
實施網路政策:使用Kubernetes NetworkPolicy或CNI提供的高階網路政策功能,限制Pod之間的通訊。採用「白名單」模式,只允許明確定義的流量。
啟用加密傳輸:在所有微服務間啟用mTLS,可以透過服務網格如Istio或Linkerd實作,或使用Cilium等CNI外掛提供的加密功能。
限制容器能力:移除所有不必要的Linux能力,特別是CAP_NET_RAW,可以透過Pod安全策略或OPA Gatekeeper實作。
監控異常流量:佈署網路流量監控工具,及時發現異常連線和流量模式。Cilium的Hubble或Calico的流量日誌功能都是不錯的選擇。
高階防護技術
工作負載身分識別:實施SPIFFE/SPIRE或服務網格的身分機制,確保所有服務間通訊都經過身分驗證。
安全邊界分層:將叢集分為多個安全區域,實施不同級別的安全控制。例如,將包含敏感資料的服務隔離在更嚴格的安全區域。
API伺服器防護:限制對API伺服器的存取,使用RBAC嚴格控制許可權,並考慮實施附加的認證機制。
節點中繼資料保護:在雲環境中,限制對節點中繼資料服務的存取,防止憑證洩露。
玄貓在實施這些策略時,通常建議分階段進行,先從最關鍵的服務開始,然後逐步擴充套件到整個叢集。這種漸進式的方法可以減少對現有服務的影響,同時確保安全措施的有效性。
安全網路設計的最佳實踐
在設計Kubernetes網路安全架構時,以下最佳實踐可以幫助建立更強大的安全防護:
架構設計考量
分層防禦:不要依賴單一安全控制,而是實施多層防禦機制。例如,結合網路政策、加密傳輸和工作負載身分識別。
最小特權原則:為每個服務和Pod分配最小必要的網路存取許可權。預設拒絕所有流量,只允許明確定義的必要通訊。
可觀測性設計:將網路流量監控和日誌記錄納入架構設計,確保能夠及時發現和回應異常行為。
維運安全實踐
定期安全掃描:使用kube-hunter、kubeaudit等工具定期掃描叢集,識別潛在的網路安全漏洞。
自動化合規檢查:實施自動化檢查,確保所有工作負載都符合組織的安全標準。OPA Gatekeeper或Kyverno是實作這一目標的好工具。
安全更新策略:建立明確的流程來及時應用CNI外掛、Ingress控制器和其他網路元件的安全更新。
演練與測試:定期進行安全演練,測試防禦機制的有效性,並識別潛在的改進領域。
玄貓在與客戶合作時發現,許多安全事故不是因為缺乏技術解決方案,而是因為缺乏持續的安全維運實踐。即使是最好的安全架構,如果沒有定期的評估和更新,也會隨著時間的推移而變得脆弱。
雲原生環境的特殊考量
在雲原生環境中佈署Kubernetes叢集時,需要特別考慮以下網路安全因素:
多雲與混合雲環境
在跨多個雲平台或混合雲/本地環境的佈署中,網路安全變得更加複雜。玄貓建議:
統一身分管理:實施跨雲的統一身分管理解決方案,確保一致的身分驗證和授權。
加密跨雲通訊:所有跨雲或雲到本地的通訊都應該加密,可以考慮使用虛擬私人網路或專用線路。
統一策略管理:使用如Anthos Config Management或Rancher Fleet等工具,確保網路安全策略在所有環境中一致應用。
服務網格的應用
服務網格技術如Istio、Linkerd或Consul提供了強大的網路安全功能:
自動mTLS:服務網格可以自動為服務間通訊啟用mTLS,無需修改應用程式碼。
細粒度存取控制:實施根據身分的授權策略,控制哪些服務可以相互通訊。
流量觀測:獲得服務間通訊的詳細可視性,幫助識別異常模式。
玄貓在實施服務網格時發現,雖然它提供了強大的安全功能,但也增加了系統的複雜性和資源消耗。因此,建議先在非生產環境中充分測試,並確保團隊具備管理服務網格的技能,再考慮在生產環境中大規模佈署。
結論
Kubernetes網路安全是一個不斷發展的領域,隨著技術的進步和威脅環境的變化,安全策略也需要不斷調整和改進。
從Pod到節點的通訊安全、叢集外部流量管理、ARP欺騙防護到工作負載身分識別,每一層面都需要周密的規劃和實施。透過採用本文討論的最佳實踐和安全加固策略,組織可以顯著提高其Kubernetes環境的安全性。
玄貓認為,未來的Kubernetes網路安全將更加註重自動化、人工智慧化和零信任架構。隨著技術的成熟,我們可以期待看到更多內建的安全功能和更簡單的安全實施方法,使得即使是資源有限的團隊也能達到高水平的安全防護。
最後,安全不是一次性的工作,而是一個持續的過程。定期評估、更新和改進你的網路安全策略,是保持Kubernetes環境安全的關鍵。
Kubernetes 網路流量安全:從預設風險到全面防護
在容器協調世界中,網路安全常被忽視,直到問題發生才引起注意。在我多年管理 Kubernetes 叢集的經驗中,發現許多工程師對 K8s 的網路預設行為認知不足,導致不必要的安全漏洞。本文將帶你從零開始建立一個測試環境,並展示如何透過網路政策來確保外部流量的安全。
預設網路行為的隱藏風險
Kubernetes 預設允許所有 Pod 之間的通訊,這種設計雖然便於開發,但在生產環境中可能造成嚴重的安全隱患。想像一下,如果一個惡意容器成功入侵你的叢集,在沒有網路限制的情況下,它可以自由地探測和攻擊叢集中的任何服務。
建立測試環境:使用 Kind 和 Calico
為了展示這些概念,我們將使用 Kind (Kubernetes IN Docker) 建立一個本地 Kubernetes 叢集,並設定 Calico 作為網路外掛來實作網路政策。
環境準備與叢集設定
首先,我們需要建立一個設定來定義我們的 Kind 叢集:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
networking:
disableDefaultCNI: true
podSubnet: 192.168.0.0/16
這個設定了一個定義包含一個控制平面節點和一個工作節點的 Kubernetes 叢集。關鍵設定包括:
- 在控制平面節點上設定
ingress-ready=true
標籤,為後續的 Ingress 控制器做準備 - 設定連線埠對映,將容器內的 80 和 443 連線埠對映到主機上,使我們能從主機直接存取服務
- 停用預設的 CNI (Container Network Interface),因為我們將使用 Calico
- 設定 Pod 網路的子網為
192.168.0.0/16
,這是 Calico 的預設設定
假設上述設定已儲存為 cluster-config.yaml
,現在我們可以建立叢集:
$ kind create cluster --name cnnp --config cluster-config.yaml
安裝與設定 Calico
接下來,我們需要安裝 Calico 網路外掛,並進行必要的修補,使其能在 Kind 環境中正常工作:
$ kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
$ kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
- 第一個命令安裝 Calico 的所有必要元件,包括 ConfigMap、CRD 和守護程式等
- 第二個命令是一個關鍵調整,設定
FELIX_IGNORELOOSERPF=true
環境變數,使 Calico 在 Kind 這種特殊環境中能正常運作。這是因為 Kind 使用 Docker 容器模擬節點,其網路設定與標準 Kubernetes 節點略有不同
確認 Calico 節點代理程式已在所有節點上執行:
$ kubectl -n kube-system get pods | grep calico-node
佈署 Ingress 控制器
為了讓外部流量能夠進入叢集,我們需要安裝 Ingress 控制器。這裡選擇使用 Ambassador 作為我們的 Ingress 控制器:
$ kubectl apply -f https://github.com/datawire/ambassador-operator/releases/latest/download/ambassador-operator-crds.yaml && \
kubectl apply -n ambassador -f https://github.com/datawire/ambassador-operator/releases/latest/download/ambassador-operator-kind.yaml && \
kubectl wait --timeout=180s -n ambassador --for=condition=deployed ambassadorinstallations/ambassador
這串命令執行了三個主要操作:
- 安裝 Ambassador 所需的自定義資源定義 (CRD)
- 在
ambassador
名稱空間中佈署 Ambassador 操作器 - 等待 Ambassador 完全佈署完成,最長等待 180 秒
佈署測試應用程式
現在基礎設施已經準備就緒,我們可以佈署一個簡單的 Web 服務來測試我們的網路設定。
建立專用名稱空間
首先,建立一個專用的名稱空間來佈署我們的應用:
$ kubectl create ns npdemo
佈署 Web 服務與 Ingress 規則
接下來,建立一個包含佈署 (Deployment)、服務 (Service) 和入口 (Ingress) 資源的設定:
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:alpine
name: main
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- port: 80
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: mainig
annotations:
kubernetes.io/ingress.class: ambassador
spec:
rules:
- http:
paths:
- path: /api
backend:
serviceName: nginx
servicePort: 80
這個設定定義了三個資源:
- Deployment:佈署一個執行 NGINX Alpine 版本的 Pod
- Service:建立一個服務,將流量轉發到帶有
app: nginx
標籤的 Pod - Ingress:設定路由規則,將
/api
路徑的請求轉發到 NGINX 服務
特別注意 Ingress 資源上的註解 kubernetes.io/ingress.class: ambassador
,這告訴 Kubernetes 使用 Ambassador 作為此 Ingress 的控制器。
將這些資源應用到叢集中:
$ kubectl -n npdemo apply -f workload.yaml
測試初始網路行為
現在讓我們測試一下是否能從外部存取我們的應用:
$ curl -s 127.0.0.1/api | wc -l
25
果然,我們收到了回應!這證實了 Kubernetes 的預設網路行為:所有流量都被允許。這種寬鬆的預設設定在生產環境中可能帶來嚴重的安全風險。
實施網路政策強化安全
現在我們將透過網路政策來限制流量,展示如何保護我們的應用免受未授權存取。
阻擋所有入站流量
首先,我們建立一個網路政策來阻擋所有入站 (Ingress) 流量:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
這個網路政策非常簡單但功能強大:
podSelector: {}
表示選擇名稱空間中的所有 PodpolicyTypes: ["Ingress"]
指定這是一個入站流量政策- 由於沒有定義任何
ingress
規則,這實際上阻擋了所有入站流量
應用這個網路政策:
$ kubectl -n npdemo apply -f np-deny-all.yaml
驗證網路政策效果
讓我們再次嘗試存取應用:
$ curl --max-time 3 127.0.0.1/api
curl: (28) Operation timed out after 3005 milliseconds with 0 bytes received
太好了!請求超時,這表明我們的網路政策生效了,成功阻擋了所有入站流量。
網路政策的除錯與管理工具
在實際環境中,網路政策的設定可能相當複雜。以下是一些有用的工具,可以幫助你管理和除錯網路政策:
- networkpolicy.io - 提供視覺化編輯器,幫助你編寫和理解網路政策
- krew-net-forward - 用於除錯網路政策的 kubectl 外掛
- netassert - 測試網路政策是否按預期工作的工具
超越網路政策的安全措施
除了 Kubernetes 網路政策,某些雲端服務提供商還提供其他本地機制來限制 Pod 的流量。例如,AWS 提供了適用於 Pod 的安全組,可以在 VPC 層面進一步加強安全性。
當我在大型金融機構實施 Kubernetes 時,發現結合 Kubernetes 網路政策與雲提供商的安全功能,可以建立深度防禦架構,大幅提高安全性。這種多層防護方法在處理敏感工作負載時尤為重要。