主要功能和優點
所有容器上的 Linux 使用者命名空間
透過增強的容器隔離,所有使用者容器都能利用 Linux 使用者命名空間 來實現額外的隔離。這表示容器中的 root 使用者會對應到 Docker Desktop Linux VM 中的非特權使用者。
例如
$ docker run -it --rm --name=first alpine
/ # cat /proc/self/uid_map
0 100000 65536
輸出 0 100000 65536
是 Linux 使用者命名空間的簽章。這表示容器中的 root 使用者 (0) 對應到 Docker Desktop Linux VM 中的非特權使用者 100000,並且對應範圍延伸至連續的 64K 使用者 ID 範圍。群組 ID 也是如此。
每個容器都會取得獨佔的對應範圍,由 Sysbox 管理。例如,如果啟動第二個容器,則對應範圍會不同
$ docker run -it --rm --name=second alpine
/ # cat /proc/self/uid_map
0 165536 65536
相反地,如果沒有增強的容器隔離,容器的 root 使用者實際上是主機上的 root(又稱為「真正的 root」),並且這適用於所有容器
$ docker run -it --rm alpine
/ # cat /proc/self/uid_map
0 0 4294967295
藉由使用 Linux 使用者命名空間,增強的容器隔離可確保容器流程永遠不會以使用者 ID 0(真正的 root)在 Linux VM 中執行。實際上,它們永遠不會使用 Linux VM 中的任何有效使用者 ID 執行。因此,它們的 Linux 功能會限制在僅限容器內的資源,與一般容器相比,顯著提高了隔離性,包括容器到主機和跨容器隔離。
具特殊權限的容器也受到保護
具特殊權限的容器 docker run --privileged ...
是不安全的,因為它們允許容器完全存取 Linux 核心。也就是說,容器以啟用所有功能的真正 root 身份執行,例如,seccomp 和 AppArmor 限制會停用,所有硬體裝置都會公開。
目標是在開發人員機器上保護 Docker Desktop 的組織,在使用具特殊權限的容器時會面臨挑戰。這些容器,無論是執行良性或惡意工作負載,都可以控制 Docker Desktop VM 中的 Linux 核心,例如,可能會變更安全性相關設定,例如登錄檔存取管理和網路代理。
透過增強的容器隔離,具特殊權限的容器將無法再執行此操作。Linux 使用者命名空間與 Sysbox 使用的其他安全技術的組合,可確保具特殊權限的容器內的流程只能存取指派給容器的資源。
注意事項
增強型容器隔離並不會阻止使用者啟動具備特權的容器,而是透過確保它們只能修改與容器相關聯的資源來安全地運行它們。 修改全域核心設定的特權工作負載,例如載入核心模組或更改 Berkeley Packet Filters (BPF) 設定將無法正常運作,因為它們在嘗試此類操作時會收到「權限被拒絕」錯誤。
例如,增強型容器隔離可確保具備特權的容器無法存取透過 BPF 設定的 Linux 虛擬機器中的 Docker Desktop 網路設定。
$ docker run --privileged djs55/bpftool map show
Error: can't get next map: Operation not permitted
相反地,如果沒有增強型容器隔離,具備特權的容器可以輕鬆地執行此操作。
$ docker run --privileged djs55/bpftool map show
17: ringbuf name blocked_packets flags 0x0
key 0B value 0B max_entries 16777216 memlock 0B
18: hash name allowed_map flags 0x0
key 4B value 4B max_entries 10000 memlock 81920B
20: lpm_trie name allowed_trie flags 0x1
key 8B value 8B max_entries 1024 memlock 16384B
請注意,某些進階容器工作負載需要具備特權的容器,例如 Docker-in-Docker、Kubernetes-in-Docker 等。使用增強型容器隔離,您仍然可以運行此類工作負載,但比以前更加安全。
容器無法與 Linux VM 共用命名空間
啟用增強型容器隔離後,容器無法與主機共享 Linux 命名空間(例如,PID、網路、uts 等),因為這基本上會破壞隔離。
例如,共享 PID 命名空間會失敗。
$ docker run -it --rm --pid=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share namespaces [pid] with the host (because they use the linux user-namespace for isolation): unknown.
同樣地,共享網路命名空間也會失敗。
$ docker run -it --rm --network=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share a network namespace with the host (because they use the linux user-namespace for isolation): unknown.
此外,用於停用容器上使用者命名空間的 --userns=host
旗標會被忽略。
$ docker run -it --rm --userns=host alpine
/ # cat /proc/self/uid_map
0 100000 65536
最後,不允許 Docker 建置 --network=host
和 Docker buildx 授權(network.host
、security.insecure
)。 需要這些的建置將無法正常運作。
繫結掛載限制
啟用增強型容器隔離後,Docker Desktop 使用者可以繼續透過 **設定** > **資源** > **檔案共享** 設定,將主機目錄繫結掛載到容器中,但他們不再允許將任意 Linux 虛擬機器目錄繫結掛載到容器中。
這可以防止容器修改 Docker Desktop Linux 虛擬機器內的敏感檔案,這些檔案可能包含登錄存取管理、代理、Docker 引擎設定等的設定。
例如,以下將 Docker 引擎的設定檔(Linux 虛擬機器內的 /etc/docker/daemon.json
)繫結掛載到容器中會受到限制,因此會失敗。
$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown
相反地,如果沒有增強型容器隔離,此掛載會正常運作,並授予容器對 Docker 引擎設定的完整讀取和寫入權限。
當然,主機檔案的繫結掛載會照常運作。 例如,假設使用者將 Docker Desktop 設定為檔案共享其 $HOME
目錄,則她可以將其繫結掛載到容器中。
$ docker run -it --rm -v $HOME:/mnt alpine
/ #
注意事項
預設情況下,增強型容器隔離不允許將 Docker 引擎通訊端 (
/var/run/docker.sock
) 繫結掛載到容器中,因為這樣做基本上會授予容器 Docker 引擎的控制權,從而破壞容器隔離。 然而,由於某些合法使用案例需要這樣做,因此可以針對受信任的容器映像放寬此限制。 請參閱Docker 通訊端掛載權限。
審查敏感的系統呼叫
增強型容器隔離的另一個功能是它會攔截並檢查容器內的一些高度敏感的系統呼叫,例如 mount
和 umount
。 這可確保具有執行這些系統呼叫能力的行程無法使用它們來突破容器。
例如,具有 CAP_SYS_ADMIN
(執行 mount
系統呼叫所需)的容器無法使用該能力將唯讀繫結掛載更改為讀寫掛載。
$ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine
/ # mount -o remount,rw /mnt /mnt
mount: permission denied (are you root?)
由於 $HOME
目錄已以唯讀方式掛載到容器的 /mnt
目錄中,因此即使容器行程有能力這樣做,也無法從容器內將其更改為讀寫。 這可確保容器行程無法使用 mount
或 umount
來突破容器的根檔案系統。
但請注意,在先前的範例中,容器仍然可以在容器內建立掛載,並根據需要將它們掛載為唯讀或讀寫。 允許這些掛載是因為它們發生在容器內,因此不會突破其根檔案系統。
/ # mkdir /root/tmpfs
/ # mount -t tmpfs tmpfs /root/tmpfs
/ # mount -o remount,ro /root/tmpfs /root/tmpfs
/ # findmnt | grep tmpfs
├─/root/tmpfs tmpfs tmpfs ro,relatime,uid=100000,gid=100000
/ # mount -o remount,rw /root/tmpfs /root/tmpfs
/ # findmnt | grep tmpfs
├─/root/tmpfs tmpfs tmpfs rw,relatime,uid=100000,gid=100000
此功能與使用者命名空間一起確保即使容器行程具有所有 Linux 功能,也無法使用它們來突破容器。
最後,增強型容器隔離以這樣的方式執行系統呼叫檢查:在大多數情況下,它不會影響容器的效能。 它會攔截大多數容器工作負載中很少使用的控制路徑系統呼叫,但不會攔截資料路徑系統呼叫。
檔案系統使用者 ID 對應
如前所述,ECI 會在所有容器上啟用 Linux 使用者命名空間。 這可確保容器的使用者 ID 範圍 (0->64K) 對應到 Docker Desktop Linux 虛擬機器中非特權的「實際」使用者 ID 範圍(例如,100000->165535)。
此外,每個容器在 Linux 虛擬機器中都會獲得一個獨佔的實際使用者 ID 範圍(例如,容器 0 可以對應到 100000->165535,容器 2 對應到 165536->231071,容器 3 對應到 231072->296607,依此類推)。 這同樣適用於群組 ID。 此外,如果容器停止並重新啟動,則無法保證它會收到與以前相同的對應。 這是設計使然,並進一步提高了安全性。
然而,當將 Docker 磁碟區掛載到容器中時,這會產生問題。 寫入此類磁碟區的檔案具有實際的使用者/群組 ID,因此由於每個容器的實際使用者 ID/群組 ID 不同,因此在容器啟動/停止/重新啟動期間或容器之間將無法存取這些檔案。
為了要解決這個問題,Sysbox 使用了 Linux 核心 ID 對應掛載功能(於 2021 年新增)或另一個名為 `shiftsfs` 的模組來進行「檔案系統使用者 ID 重新對應」。這些技術會將檔案系統的存取動作,從容器的實際使用者 ID(例如,範圍 100000->165535)對應到 Docker Desktop Linux 虛擬機器內的範圍 (0->65535)。透過這種方式,磁碟區現在可以跨容器掛載或共享,即使每個容器使用獨佔的使用者 ID 範圍。使用者不需要擔心容器的實際使用者 ID。
儘管檔案系統使用者 ID 重新對應可能會導致容器使用實際使用者 ID 0 存取掛載到容器中的 Linux 虛擬機器檔案,但受限掛載功能可確保無法將敏感的 Linux 虛擬機器檔案掛載到容器中。
Procfs 與 sysfs 模擬
增強型容器隔離的另一個功能是在每個容器內,/proc
和 /sys
檔案系統會被部分模擬。 這有幾個目的,例如在容器內隱藏敏感的主機資訊,以及將 Linux 核心本身尚未命名空間化的主機核心資源命名空間化。
舉一個簡單的例子,當啟用增強型容器隔離時,/proc/uptime
檔案會顯示容器本身的正常運行時間,而不是 Docker Desktop Linux 虛擬機器的正常運行時間。
$ docker run -it --rm alpine
/ # cat /proc/uptime
5.86 5.86
相反地,如果沒有增強型容器隔離,您會看到 Docker Desktop Linux 虛擬機器的正常運行時間。 雖然這是一個微不足道的例子,但它顯示了增強型容器隔離如何旨在防止 Linux 虛擬機器的設定和資訊洩漏到容器中,從而使其更難以突破虛擬機器。
此外,/proc/sys
下的其他幾個 Linux 核心尚未命名空間化的資源也在容器內進行模擬。 每個容器都會看到每個此類資源的單獨視圖,並且 Sysbox 在對應的 Linux 核心設定進行程式設計時會協調容器之間的值。
這具有以下優點:啟用容器工作負載(否則需要真正具備特權的容器才能存取此類未命名空間化的核心資源)以在啟用增強型容器隔離的情況下運行,從而提高安全性。