在CentOS上為Docker開啟SELinux


生產服務器使用的是CentOS 7系統,安裝Docker也一直都是使用yum命令直接從CentOS自己的源安裝。自從Docker項目改名為moby,進而誕生CE和EE兩個不同版本后。不知是因為版權還是其他的什么原因,CentOS源中的Docker版本不再更新了,default維持在1.12.6,latest為1.13.1。

為了使用新版本的Docker,只能添加官方repo,然后安裝docker-ce。安裝完成后,在默認配置上與CentOS自帶版相比,發現了兩個不同之處:

  1. 存儲驅動默認換成了overlay
  2. SELinux默認沒有開啟(指Docker服務配置)

分析

關於存儲驅動的問題,這里暫時不做討論,只是來看一下SELinux的問題。這里說的SELinux沒有開啟不是指在操作系統層面上將其disable掉了,而是說Docker服務的配置中沒有將其enable。畢竟在Docker中開啟SELinux是要在操作系統也就是Linux內核開啟了SELinux的前提下進行的。首先,Docker沒有開啟SELinux,在現象上會有什么不同?

我們有兩台服務器,第一台上Docker開啟了SELinux,而第二台沒有。兩台上面都有運行nginx容器,執行如下命令對比一下:

[admin@server1 ~]$ ps -AZ | grep nginx
system_u:system_r:svirt_lxc_net_t:s0:c375,c378 2285 ? 00:00:22 nginx
system_u:system_r:svirt_lxc_net_t:s0:c245,c772 2407 ? 00:00:00 nginx
system_u:system_r:svirt_lxc_net_t:s0:c245,c772 2453 ? 00:00:02 nginx
system_u:system_r:svirt_lxc_net_t:s0:c375,c378 24771 ? 00:00:00 nginx
[admin@server2 ~]$ ps -AZ | grep nginx
system_u:system_r:spc_t:s0       4375 ?        00:00:00 nginx
system_u:system_r:spc_t:s0       4419 ?        00:00:00 nginx
system_u:system_r:spc_t:s0       4739 ?        00:00:01 nginx
system_u:system_r:spc_t:s0       4752 ?        00:00:01 nginx
system_u:system_r:spc_t:s0       9536 ?        00:00:00 nginx
system_u:system_r:spc_t:s0       9564 ?        00:00:00 nginx
system_u:system_r:spc_t:s0      19178 ?        00:00:00 nginx
system_u:system_r:spc_t:s0      19255 ?        00:00:00 nginx

通過對比,我們發現開啟SELinux后的Docker服務:

  1. 容器內的進程運行在svirt_lxc_net_t domain下
  2. 不同容器內的進程,安全上下文sensitivity段是不相同的(SELinux的MCS隔離)

對於沒有開啟SELinux的Docker服務:

  1. 容器進程domain為spc_t
  2. 所有容器進程的安全上下文sensitivity完全相同

根據以上對比,顯而易見的是,在SElinux沒有開啟時容器進程擁有相同的sensitivity,所以就無法依賴SELinux實現容器間的安全隔離了。也就是說如果某個容器內的服務進程因為漏洞等原因被入侵,進而被黑客控制,SELinux不會阻止此進程去訪問其他容器的資源。

對於svirt_lxc_net_tspc_t,可能第一眼看來不會有那么多的想法,我們先來看看svirt_lxc_net_t的進程是個什么體驗:

[admin@server2 ~]$ runcon -u system_u -r system_r -t svirt_lxc_net_t -l s0:c125,c512 /bin/bash
bash: /home/admin/.bashrc: Permission denied
bash-4.2$ ls
ls: cannot open directory .: Permission denied
bash-4.2$ ps -Z
system_u:system_r:svirt_lxc_net_t:s0:c125,c512 23686 pts/0 00:00:00 bash
system_u:system_r:svirt_lxc_net_t:s0:c125,c512 23722 pts/0 00:00:00 ps
bash-4.2$

因為當前目錄的安全上下文類型是user_home_t,按照SELinux策略,svirt_lxc_net_t是沒有權限訪問的。雖然能夠感受到進程確實受到了限制,但是還不是很直觀。接下來用sepolicy命令分析一下安全策略:

[admin@server2 ~]$ sepolicy communicate -s svirt_lxc_net_t -t svirt_lxc_net_t
sysctl_net_unix_t
cifs_t
svirt_lxc_net_t
fusefs_t
cgroup_t
svirt_sandbox_file_t
usermodehelper_t
svirt_home_t
hugetlbfs_t
nfs_t

根據man page中的說明,這個命令用來分析source和target兩個domain可以通過哪些type來通信,也就是哪些type對於source來說可寫,對於target來說可讀。我們把source和target指定為同一domain,來看看該domain能夠讀寫哪些type。

我們看到了,一個很熟悉的svirt_sandbox_file_t,正是給Docker容器掛載volume時經常看到、用到的。據了解svirt_lxc_net_t相關策略就是為容器、虛擬化技術而設計的,除了可以訪問svirt_sandbox_file_t類型的文件還擁有網絡能力,並且可以執行/usr下大多數的命令。

再用以上命令看一下spc_t,因為行數太多,所以做一下統計:

[admin@server2 ~]$ sepolicy communicate -s spc_t -t spc_t | wc -l 
3816
[admin@server2 ~]$ sepolicy communicate -s unconfined_t -t unconfined_t | wc -l      
3816

根據當前的安全策略,3816個type,比起svirt_lxc_net_t的10個,不可同日而語。而且我們發現,不受限domain unconfined_t也是3816。那么spc_t就等於unconfined_t了嗎?其實也不是。

根據Dan Walsh的Blog所講,unconfined_t是為管理員而設置的一個user domain,SELinux安全策略會阻止絕大多數的受限domain和unconfined_t通信。spc_t全稱為Super Privileged Container,也就是特權容器。根據SELinux策略,Docker daemon container_runtime_t可以通過transition轉變為spc_t,而且大多數重要的受限domain可以通過unix domain socket和spc_t進行通信。

配置

上面的分析只是為了對SELinux對Docker的影響有更深入地了解,同時感受SELinux的重要性。其實在Docker服務配置中開啟SELinux很簡單:

  1. 一種方法是在dockerd啟動時加上--selinux-enabled參數,在CentOS上可以修改systemd Unit文件docker.service
  2. 另一種方法實在/etc/docker/daemon.json配置文件中加上:
    {
     "selinux-enabled": true
    }
    
    然后重啟docker服務

需要注意的是,在SELinux開啟之前創建的容器不會受到影響。如果要為這些容器應用SELinux,可以重建,或者嘗試自己修改容器的配置文件和文件系統。

參考

  1. 官方文檔 https://docs.docker.com/edge/engine/reference/commandline/dockerd/
  2. Dan Walsh的Blog https://danwalsh.livejournal.com/74754.html
  3. https://help.replicated.com/docs/kb/supporting-your-customers/selinux/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM