天天看點

使用User Namespaces,隔離容器應用

作者:神奇的工程師

容器内的root使用者映射到主控端也是root使用者。這就意味着,容器應用提升到root權限後,也相當于獲得了主控端的root權限。

為了加強使用者權限管控,可以為Docker開啟User Namespaces機制。

通過 user namespace 技術,可以把容器中的 root 使用者映射為主控端的一個普通使用者(隻有普通權限的使用者)。應用在容器中以為自己是以root身份運作,具有root權限。實際上它在主控端上使用的隻是普通使用者身份,擁有有限的權限。

User Namespaces和subuid

User Namespaces (使用者命名空間)是在Linux核心3.8版本引入,作為Namespaces安全機制的一部分。這也意味着目前流行的Linux和Docker版本都是支援的。

這裡,首先需要了解subuid和subgid的概念。

Linux系統是使用uid來辨別一個使用者。root使用者的uid為0。

Linux可以通過/etc/subuid檔案為使用者配置一些從屬使用者。預設情況下,使用者的subuid從100000開始,每組65536個。這裡我已經建立了一個使用者u​,因為它前面還有幾個使用者,是以其subuid是從296608開始的65536個。

同理,Linux系統也可以通過/etc/subgid​配置從屬組。

再看看subuid在使用者命名空間中的意義。

初始狀态下,Linux使用的是一個預設使用者空間。為使用者指定了從屬使用者,在對應的子使用者空間中,子控件的使用者可以被映射到這些從屬使用者。

這樣一來,使用者u對應的子使用者空間中,uid=0的root使用者,實際映射的是主控端上uid=296608的使用者。

為Docker啟用User Namespaces

可以修改/etc/subuid​和/etc/subguid​,為使用者u​設定好從屬使用者和從屬使用者組。

然後在/etc/docker/daemon.json​中配置使用者命名空間:

{
"userns-remap":"u"
}           

或者,把userns-remap​設定為default,讓Docker自動完成配置:

{
"userns-remap": "default"
}           

預設的使用者命名空間最大數量(max_user_namespaces)可能為0,會Docker導緻無法建立使用者命名空間,出現錯誤提示:nsenter: failed to unshare namespaces: Invalid argument​。

檢視/proc/sys/user/max_user_namespaces​,可以獲得該配置。如果為0,可以通過下列指令增大。

sysctl user.max_user_namespaces=15000           

然後,重新開機docker: systemctl restart docker.service​。

此時,Docker容器應用就運作在一個特定使用者空間了。

可以在主控端上看到生成的新目錄/var/lib/docker/296608.296608​。此時,docker的根目錄變成了這個新目錄,而不是原來的/var/lib/docker​。此時,使用docker ls​ 也看不到原來的images了。

使用User Namespaces,隔離容器應用
使用User Namespaces,隔離容器應用

以nginx容器為例,雖然容器内是以root使用者運作nginx master程序,并使用普通使用者運作了2個nginx worker程序。

容器内的root使用者,被映射到主控端是普通使用者296608。容器内的普通使用者(nginx),被映射到主控端是普通使用者296709。

使用User Namespaces,隔離容器應用
使用User Namespaces,隔離容器應用

如果仍希望使用root使用者來啟動容器呢?可以使用--userns=host​來解決。

此時,容器root使用者映射到宿主root使用者,容器普通使用者映射到宿主普通使用者,等同于不使用User Namespace的預設情況。

使用User Namespaces,隔離容器應用

總結

用一張圖來看看user namespaces的作用。

使用User Namespaces,隔離容器應用

Docker使用user namespaces後,容器應用不論是以root使用者還是普通使用者身份運作,在主控端上實際都是普通使用者權限,這就大大提高了安全性。

繼續閱讀