一.docker與虛擬機的差別
隔離與共享
- 每個虛擬機都有自己的系統內核
- docker容器則是通過隔離的方式讓容器之間相互影響,但是容器無法影響宿主機
性能與損耗
- 與虛擬機相比,容器的資源損耗要小的多
- 同樣在宿主機之下,能夠建立的容器數量要比虛擬機多
- 但是虛擬機的安全性要好於容器
二.docker的安全問題以及架構缺陷
安全問題
- docker自身漏洞:CVE官方記錄docker歷史版本共有超過20項漏洞
- docker的源碼問題:黑客上傳惡意鏡像、鏡像使用有漏洞的軟件、中間人攻擊篡改鏡像
架構缺陷
- 容器之間的局域網攻擊
- DDos攻擊耗盡資源
- 有漏洞的系統調用
- 共享root用戶權限
三.docker的安全基線標準
- docker的安全基線標準包括:內核、主機、網絡、鏡像、容器、其他
內核級別
- 及時更新內核
- User Namespace(容器內的root權限在容器之外處於非高權限的狀態)
- Cgroups(對資源的配額和度量)
- SElinux/AppArmor/GRSEC(控制文件訪問權限)
- Capability(權限劃分)
- Seccomp(限定系統調用)
- 禁止將容器的命名空間與宿主機進程命名空間共享
主機級別
- 爲容器創建獨立分區
- 僅運行必要的服務
- 禁止將宿主機上的敏感目錄映射到容器
- 對docker守護進程、相關文件和目錄進行審計
- 設置適當的默認文件描述符數。(問價描述符:內核(kernel)利用文件描述符(file descriptor)來訪問文件。文件描述符是非負整數。打開現存文件或者新建文件時,內核會返回一個文件描述符。讀寫文件也需要使用文件描述符來指定待鍍錫的文件)
- 用戶權限爲root的docker相關文件的訪問權限應該爲644或者更低權限
- 週期性檢查每個主機的容器清單,並且清理不必要的容器
網絡級別
- 通過iptables設定規則實現禁止或者允許容器之間網絡流量
- 允許docker修改iptables
- 禁止docker綁定到其他IP/port或者unix socket
- 禁止在容器上映射特權端口。
- 容器上只開放所需要的端口
- 禁止在容器上使用主機網絡模式
- 若宿主機上有多個網卡,將容器進入流量綁定到特定的主機網卡上
鏡像級別
- 創建本地鏡像倉庫服務器
- 鏡像中軟件都爲最新版本
- 使用可信鏡像文件,並且通過安全通道下載
- 重新構建鏡像而非對容器和鏡像打補丁
- 合理管理鏡像標籤,及時移除不再使用的鏡像。
- 使用鏡像掃描
- 使用鏡像簽名
容器級別
- 容器最小化,操作系統鏡像最小集
- 容器以單一主進程的方式運行
- 禁止privileged標記使用特權容器
- 禁止在容器上運行ssh服務
- 以只讀的方式掛載容器的根目錄系統
- 明確定義屬於容器的數據盤符
- 通過設置on-failure限制容器嘗試重啓的次數,容器反覆重啓容易丟失數據
- 限制在容器中可用的進程樹,以防止fork bomb。(fork炸彈,迅速增長子進程,耗盡系統進程數量)
其他設置
- 定期對宿主機系統以及容器進行安全審計
- 使用最少的資源和最低權限運行容器
- 避免在同一宿主機上部署大量的容器,維持一個能夠管理的數量
- 監控docker容器的使用,性能以及其他各項指標
- 增加實時威脅檢測和事件響應功能
- 使用中心和遠程日誌收集服務
四.docker安全通信的措施
容器最小化
- 如果僅在容器與運行必要的服務,那麼像ssh、telnet等服務就不能輕易開啓連接容器,通常使用以下方式進入容器
docker exec -it 容器ID bash
docker remote api訪問控制
- 對於docker的遠程調用API接口存在未授權訪問的漏洞,至少應該限制外網的訪問,可以使用socket的方式訪問,監聽內網ip,docker daemon 啓動方式如下:
1.使用命令配置socket的訪問方式
//客戶端連接docker服務時,通過對應IP地址和端口進行連接,這個端口可以選擇
docker -d -H uninx:///var/run/docker.sock -H tcp://192.168.43.101:2375
2.修改docker的配置文件,實現socket訪問
vi /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 192.168.43.101:2375
#重啓docker服務
systemctl deamon-reload
systemctl restart docker
[root@192 ~]# netstat -natp | grep dockerd
tcp 0 0 192.168.43.101:2375 0.0.0.0:* LISTEN 37179/dockerd
[root@192 ~]#
#在宿主機上配置firewalld的訪問控制策略
[root@192 ~]# firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.43.101" port protocol="tcp" port="2379" accept"
success
[root@192 ~]# firewall-cmd --reload
success
[root@192 ~]#
限制流量流向(向外的數據)
- 使用防火牆限制docker容器的源IP地址範圍與外界通訊
[root@192 ~]# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.43.0/24" reject"
success
[root@192 ~]#
#permanent永久設置
#add-rich-rule添加規則
#reject拒絕
#source address源地址爲容器地址,出去的數據
- 大量的問題是因爲docker容器端口外放引起的漏洞,除了操作系統賬戶權限控制上的問題,更在於對docker daemon進程管理上存在隱患
- 目前常用的docker版本都支持docker daemon管理宿主機的iptables,而且一旦啓動進程加上 -p host_port:guset_port的端口映射,Docker Daemon會直接增加對應的FORWARD chain並且-j ACCEPT,而默認的DROP規則是在INPUT鏈上做的,對docker沒辦法限制,這就留下了很嚴重的安全隱患
建議如下:
①不在有外網的機器上使用docker服務
②使用k8s等docker編排系統管理docker容器
③宿主機上的Docker Daemon啓動命令上加一個 --iptables=false,然後把常用的iptables寫進入文件裏,再用iptables-restore
鏡像安全
- docker鏡像安全掃描,在鏡像倉庫客戶端使用證書認證,對下載的鏡像進行檢查,通過與CVE數據庫同步掃描鏡像,一旦發生漏洞則通知用戶處理,或者直接阻止繼續構建
- 如果公司使用的是自己的鏡像源,可以跳過此步驟;否則至少需要驗證basetime的md5等特徵值,確定一致後在基於basetime進一步構建,一般情況下,要確保只從受信任的庫中獲取鏡像,並且不建議使用 --insecure-registry=[ ] 參數。