本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
在 Ingress-NGINX v1.2.0 中提高安全標準
Ingress 可能是 Kubernetes 中最常被攻擊的元件之一。Ingress 通常定義了一個暴露給網際網路的 HTTP 反向代理,其中包含多個網站,並擁有對 Kubernetes API 的一些特權訪問(例如讀取與 TLS 證書及其私鑰相關的 Secret)。
雖然它在您的架構中是一個有風險的元件,但它仍然是正確暴露服務的最流行方式。
Ingress-NGINX 經過安全評估後發現一個大問題:在將配置轉換為 nginx.conf
檔案之前,我們沒有進行所有適當的清理,這可能導致資訊洩露風險。
儘管我們理解這種風險以及修復它的真正需求,但這不是一個簡單的過程,因此我們採取了另一種方法來降低(但不能消除!)當前(v1.2.0)版本中的這種風險。
隆重推出 Ingress NGINX v1.2.0 和 chroot NGINX 程序
主要的挑戰之一是 Ingress-NGINX 將 Web 代理伺服器(NGINX)與 Ingress 控制器(具有 Kubernetes API 訪問許可權並建立 nginx.conf
檔案的元件)一起執行。
因此,NGINX 確實擁有與控制器相同的檔案系統訪問許可權(以及 Kubernetes 服務帳戶令牌以及容器中的其他配置)。雖然將這些元件分離是我們的最終目標,但專案需要快速響應;這促使我們考慮使用 chroot()
。
讓我們看看在這次更改之前 Ingress-NGINX 容器是什麼樣子
正如我們所看到的,提供 HTTP 代理的容器(不是 Pod,而是容器!)是監視 Ingress 物件並寫入容器卷的容器
現在,認識一下新架構
這一切意味著什麼?一個基本的總結是:我們將 NGINX 服務隔離為控制器容器內的容器。
雖然這並非完全準確,但要理解這裡所做的工作,最好了解 Linux 容器(以及 cgroup 等底層機制和核心名稱空間)的工作原理。您可以在 Kubernetes 詞彙表中閱讀有關 cgroup 的內容:cgroup
,並在 NGINX 專案文章 名稱空間和 cgroup 是什麼,它們如何工作? 中瞭解 cgroup 如何與名稱空間互動。(在您閱讀時,請記住 Linux 核心名稱空間與 Kubernetes 名稱空間是不同的概念)。
跳過理論,我需要什麼才能使用這種新方法?
雖然這會提高安全性,但我們在本次釋出中將此功能設定為可選,以便您有時間在環境中進行正確的調整。此新功能僅適用於 Ingress-NGINX 控制器 v1.2.0 及更高版本。
要使用此功能,您的部署需要進行兩項更改
- 在容器映象名稱後附加 "-chroot" 字尾。例如:
gcr.io/k8s-staging-ingress-nginx/controller-chroot:v1.2.0
- 在您的 Ingress 控制器的 Pod 模板中,找到新增能力
NET_BIND_SERVICE
的位置,並新增能力SYS_CHROOT
。編輯清單後,您將看到類似以下的程式碼片段
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
- SYS_CHROOT
如果您使用官方 Helm chart 部署控制器,則更改 values.yaml
中的以下設定
controller:
image:
chroot: true
Ingress 控制器通常是叢集範圍的(IngressClass API 是叢集範圍的)。如果您管理 Ingress-NGINX 控制器但不是整個叢集的運營者,則在您的部署中啟用 SYS_CHROOT
功能**之前**,請諮詢您的叢集管理員是否可以使用該功能。
好的,但這如何提高我的 Ingress 控制器的安全性?
考慮以下配置片段,並想象出於某種原因它被新增到了您的 nginx.conf
中
location /randomthing/ {
alias /;
autoindex on;
}
如果您部署此配置,則有人可以透過呼叫 http://website.example/randomthing
獲取 Ingress 控制器整個檔案系統的列表(和訪問許可權)。
現在,您能識別出下方列表中 chroot 和非 chroot Nginx 之間的區別嗎?
無額外的 chroot() | 有額外的 chroot() |
---|---|
bin | bin |
dev | dev |
etc | etc |
home | |
lib | lib |
media | |
mnt | |
opt | opt |
proc | proc |
root | |
run | run |
sbin | |
srv | |
sys | |
tmp | tmp |
usr | usr |
var | var |
dbg | |
nginx-ingress-controller | |
wait-shutdown |
左側的沒有 chroot。因此 NGINX 對檔案系統擁有完全訪問許可權。右側的進行了 chroot,因此建立了一個只包含使 NGINX 工作所需檔案的新檔案系統。
此版本中還有哪些其他安全改進?
我們知道新的 chroot()
機制有助於解決部分風險,但是,仍然有人可以嘗試注入命令來讀取,例如,nginx.conf
檔案並提取敏感資訊。
因此,此版本中的另一項更改(這是可選退出!)是“深度檢查器”。我們知道某些指令或正則表示式可能對 NGINX 危險,因此深度檢查器會檢查 Ingress 物件的所有欄位(在其協調期間,以及透過驗證准入 Webhook),以驗證是否有任何欄位包含這些危險指令。
Ingress 控制器已經對註解執行此操作,我們的目標是在未來版本中將此現有驗證移到深度檢查中。
您可以在 https://github.com/kubernetes/ingress-nginx/blob/main/internal/ingress/inspector/rules.go 中檢視現有規則。
由於需要檢查和匹配相關 Ingress 物件中的所有字串,此新功能可能會消耗更多 CPU。您可以透過在命令列引數中執行 --deep-inspect=false
來停用它。
接下來是什麼?
這並非我們的最終目標。我們的最終目標是將控制平面和資料平面程序分離。事實上,這樣做也將有助於我們實現 Gateway API 實現,因為一旦它“知道”要向資料平面提供什麼,我們可能會有不同的控制器(這裡需要一些幫助!!)
Kubernetes 中的其他一些專案已經採取了這種方法(例如 KPNG,kube-proxy
的擬議替代品),我們計劃與它們保持一致,並在 Ingress-NGINX 中獲得相同的體驗。
進一步閱讀
如果您想了解 Ingress NGINX 中如何實現 chroot,請檢視 https://github.com/kubernetes/ingress-nginx/pull/8337。包含所有更改的 v1.2.0 版本可在 https://github.com/kubernetes/ingress-nginx/releases/tag/controller-v1.2.0 找到。