容器的安全性問題的根源在于容器和宿主機(jī)共享內(nèi)核。如果容器里的應(yīng)用導(dǎo)致Linux內(nèi)核崩潰,那么整個(gè)系統(tǒng)可能都會(huì)崩潰。與虛擬機(jī)是不同的,虛擬機(jī)并沒有與主機(jī)共享內(nèi)核,虛擬機(jī)崩潰一般不會(huì)導(dǎo)致宿主機(jī)崩潰。
Docker 容器與虛擬機(jī)的區(qū)別
-
隔離與共享
虛擬機(jī)通過添加 Hypervisor 層(虛擬化中間層),虛擬出網(wǎng)卡、內(nèi)存、CPU 等虛擬硬件,再在其上建立虛擬機(jī),每個(gè)虛擬機(jī)都有自己的系統(tǒng)內(nèi)核。
而Docker容器則是通過隔離的方式,將文件系統(tǒng)、進(jìn)程、設(shè)備、網(wǎng)絡(luò)等資源進(jìn)行隔離,再對(duì)權(quán)限、CPU 資源等進(jìn)行控制,最終讓容器之間互不影響,容器無(wú)法影響宿主機(jī)。
容器與宿主機(jī)共享內(nèi)核、文件系統(tǒng)、硬件等資源。 -
性能與損耗
與虛擬機(jī)相比,容器資源損耗要少。同樣的宿主機(jī)下,能夠建立容器的數(shù)量要比虛擬機(jī)多。
但是,虛擬機(jī)的安全性要比容器稍好,要從虛擬機(jī)攻破到宿主機(jī)或其他虛擬機(jī),需要先攻破 Hypervisor 層,這是極其困難的。
而 docker 容器與宿主機(jī)共享內(nèi)核、文件系統(tǒng)等資源,更有可能對(duì)其他容器、宿主機(jī)產(chǎn)生影響。
同點(diǎn) | Docker容器 | 虛擬機(jī) |
---|---|---|
啟動(dòng)速度 | 快,幾秒鐘 | 慢,幾分鐘 |
運(yùn)行性能 | 接近原生(直接在內(nèi)核中運(yùn)行) | 運(yùn)行于Hypervisor上,50%左右損失 |
磁盤占用 | 小,甚至幾十KB(根據(jù)鏡像層的情況) | 非常大,上GB |
并發(fā)性 | 一臺(tái)宿主機(jī)可以啟動(dòng)成百上千個(gè)容器 | 最多幾十個(gè)虛擬機(jī) |
隔離性 | 進(jìn)程級(jí)別 | 系統(tǒng)級(jí)別(更徹底) |
操作系統(tǒng) | 主要支持Linux | 幾乎所有 |
封裝程度 | 只打包項(xiàng)目代碼和依賴關(guān)系,共享宿主機(jī)內(nèi)核 | 完整的操作系統(tǒng),與宿主機(jī)隔離 |
Docker 存在的安全問題
1.Docker 自身漏洞
作為一款應(yīng)用 Docker 本身實(shí)現(xiàn)上會(huì)有代碼缺陷。CVE 官方記錄 Docker 歷史版本共有超過 20 項(xiàng)漏洞,可參見 Docker 官方網(wǎng)站。
黑客常用的攻擊手段主要有代碼執(zhí)行、權(quán)限提升、信息泄露、權(quán)限繞過等。目前 Docker 版本更迭非??欤珼ocker 用戶可將 Docker 升級(jí)為最新版本。
2.Docker 源碼問題
Docker 提供了 Docker hub,可以讓用戶上傳創(chuàng)建的鏡像,以便其他用戶下載,快速搭建環(huán)境。但同時(shí)也帶來(lái)了一些安全問題。
例如下面三種方式:
(1)黑客上傳惡意鏡像
如果有黑客在制作的鏡像中植入木馬、后門等惡意軟件,那么環(huán)境從一開始就已經(jīng)不安全了,后續(xù)更沒有什么安全可言。
(2)鏡像使用有漏洞的軟件
DockerHub上能下載的鏡像里面,75%的鏡像都安裝了有漏洞的軟件。所以下載鏡像后,需要檢查里面軟件的版本信息,對(duì)應(yīng)的版本是否存在漏洞,并及時(shí)更新打上補(bǔ)丁。
(3)中間人攻擊篡改鏡像
鏡像在傳輸過程中可能被篡改,目前新版本的 Docker 已經(jīng)提供了相應(yīng)的校驗(yàn)機(jī)制來(lái)預(yù)防這個(gè)問題。
Docker 架構(gòu)缺陷與安全機(jī)制
Docker本身的架構(gòu)與機(jī)制就可能產(chǎn)生問題,例如這樣一種攻擊場(chǎng)景,黑客已經(jīng)控制了宿主機(jī)上的一些容器,或者獲得了通過在公有云上建立容器的方式,然后對(duì)宿主機(jī)或其他容器發(fā)起攻擊。
-
容器之間的局域網(wǎng)攻擊
主機(jī)上的容器之間可以構(gòu)成局域網(wǎng),因此針對(duì)局域網(wǎng)的ARP欺騙、端口掃描、廣播風(fēng)暴等攻擊方式便可以用上。
所以,在一個(gè)主機(jī)上部署多個(gè)容器需要合理的配置網(wǎng)絡(luò)安全,比如設(shè)置 iptables 規(guī)則。 -
DDoS 攻擊耗盡資源
Cgroups 安全機(jī)制就是要防止此類攻擊的,不要為單一的容器分配過多的資源即可避免此類問題。 -
有漏洞的系統(tǒng)調(diào)用
Docker 與虛擬機(jī)的一個(gè)重要的區(qū)別就是 Docker 與宿主機(jī)共用一個(gè)操作系統(tǒng)內(nèi)核。
一旦宿主內(nèi)核存在可以越權(quán)或者提權(quán)漏洞,盡管Docker使用普通用戶執(zhí)行,在容器被入侵時(shí),攻擊者還可以利用內(nèi)核漏洞跳到宿主機(jī)做更多的事情。 -
共享root用戶權(quán)限
如果以 root 用戶權(quán)限運(yùn)行容器(docker run --privileged),容器內(nèi)的 root 用戶也就擁有了宿主機(jī)的root權(quán)限。
Docker 安全基線標(biāo)準(zhǔn)
下面從內(nèi)核、主機(jī)、網(wǎng)絡(luò)、鏡像、容器以及其它等 6 個(gè)方面總結(jié) Docker 安全基線標(biāo)準(zhǔn)。
-
內(nèi)核級(jí)別
(1)及時(shí)更新內(nèi)核。
(2)User NameSpace(容器內(nèi)的 root 權(quán)限在容器之外處于非高權(quán)限狀態(tài))。
(3)Cgroups(對(duì)資源的配額和度量),設(shè)置CPU、內(nèi)存、磁盤 IO等資源限制。
(4)通過啟用 SELinux(控制文件訪問權(quán)限)適當(dāng)?shù)膹?qiáng)化系統(tǒng)來(lái)增加額外的安全性。
(5)Capability(權(quán)限劃分),比如劃分指定的CPU給容器。
(6)Seccomp(限定系統(tǒng)調(diào)用),限制不必要的系統(tǒng)調(diào)用。
(7)禁止將容器的命名空間與宿主機(jī)進(jìn)程命名空間共享,比如 host 網(wǎng)絡(luò)模式。 -
主機(jī)級(jí)別
(1)為容器創(chuàng)建獨(dú)立分區(qū),比如創(chuàng)建在分布式文件系統(tǒng)上。
(2)僅運(yùn)行必要的服務(wù),注意盡量避免在容器中運(yùn)行 ssh 服務(wù) 。
(3)禁止將宿主機(jī)上敏感目錄映射到容器,-v創(chuàng)建數(shù)據(jù)卷時(shí)需要注意。
(4)對(duì) Docker 守護(hù)進(jìn)程、相關(guān)文件和目錄進(jìn)行審計(jì),防止有病毒或木馬文件生成。
(5)設(shè)置適當(dāng)?shù)哪J(rèn)文件描述符數(shù)。
(6)用戶權(quán)限為 root 的 Docker 相關(guān)文件的訪問權(quán)限應(yīng)該為 644 或者更低權(quán)限。
(7)周期性檢查每個(gè)主機(jī)的容器清單,并清理不必要的容器。 -
網(wǎng)絡(luò)級(jí)別
(1)通過 iptables 設(shè)定規(guī)則實(shí)現(xiàn)禁止或允許容器之間網(wǎng)絡(luò)流量。
(2)允許 Docker 修改 iptables。
(3)禁止將 Docker 綁定到其他已使用的 IP/Port 或者 Unix Socket。
(4)禁止在容器上映射特權(quán)端口。
(5)容器上只開放所需要的端口。
(6)禁止在容器上使用 host 網(wǎng)絡(luò)模式。
(7)若宿主機(jī)有多個(gè)網(wǎng)卡,將容器進(jìn)入流量綁定到特定的主機(jī)網(wǎng)卡上。
docker network create --subnet=172.18.0.0/16 --opt “com.docker.network.bridge.name”=“docker1” mynetwork
docker run -itd --net mynetwork --ip 172.18.0.100 centos:7 /bin/bash
iptables -t nat -A POSTROUTING -s 172.18.0.100 -o ens36 -j SNAT --to-source 192.168.80.10 -
鏡像級(jí)別
(1)創(chuàng)建本地私有鏡像倉(cāng)庫(kù)服務(wù)器。
(2)鏡像中軟件都為最新版本,建議根據(jù)實(shí)際情況使用對(duì)應(yīng)版本,業(yè)務(wù)穩(wěn)定優(yōu)先。
(3)使用可信鏡像文件,并通過安全通道下載。
(4)重新構(gòu)建鏡像而非對(duì)容器和鏡像打補(bǔ)丁,銷毀異常容器重新構(gòu)建。
(5)合理管理鏡像標(biāo)簽,及時(shí)移除不再使用的鏡像。
(6)使用鏡像掃描。
(7)使用鏡像簽名。 -
容器級(jí)別
(1)容器最小化,操作系統(tǒng)鏡像最小集。
(2)容器以單一主進(jìn)程的方式運(yùn)行。
(3)禁止 --privileged 標(biāo)記使用特權(quán)容器。
(4)禁止在容器上運(yùn)行 ssh 服務(wù),盡量使用 docker exec 進(jìn)入容器。
(5)以只讀的方式掛載容器的根目錄系統(tǒng),-v 宿主機(jī)目錄:容器目錄:ro。
(6)明確定義屬于容器的數(shù)據(jù)盤符。
(7)通過設(shè)置 on-failure 限制容器嘗試重啟的次數(shù),容器反復(fù)重啟容易丟失數(shù)據(jù),–restart=on-failure:3。
(8)限制在容器中可用的進(jìn)程數(shù),docker run -m 限制內(nèi)存的使用,以防止 fork 炸彈。 (fork炸彈,迅速增長(zhǎng)子進(jìn)程,耗盡系統(tǒng)進(jìn)程數(shù)量).(){.|.&};. -
其他設(shè)置
(1)定期對(duì)宿主機(jī)系統(tǒng)及容器進(jìn)行安全審計(jì)。
(2)使用最少資源和最低權(quán)限運(yùn)行容器,此為 Docker 容器安全的核心思想。
(3)避免在同一宿主機(jī)上部署大量容器,維持在一個(gè)能夠管理的數(shù)量。
(4)監(jiān)控 Docker 容器的使用,性能以及其他各項(xiàng)指標(biāo),比如 zabbix。
(5)增加實(shí)時(shí)威脅檢測(cè)和事件報(bào)警響應(yīng)功能,比如 zabbix。
(6)使用中心和遠(yuǎn)程日志收集服務(wù),比如 ELK 。
由于安全屬于非常具體的技術(shù),這里不再贅述,可直接參閱 Docker 官方文檔,https://docs.docker.com/engine/security/
容器相關(guān)的常用安全配置方法
- 容器最小化
如果僅在容器中運(yùn)行必要的服務(wù),像 SSH 等服務(wù)是不能輕易開啟去連接容器的。通常使用以下方式來(lái)進(jìn)入容器。
docker exec -it a661258f6bfe bash
- Docker 遠(yuǎn)程 API 訪問控制
Docker 的遠(yuǎn)程調(diào)用API 接口存在未授權(quán)訪問漏洞,至少應(yīng)限制外網(wǎng)訪問。建議使用 Socket 方式訪問。
//在 docker 服務(wù)配置文件指定監(jiān)聽內(nèi)網(wǎng) ip
vim /usr/lib/systemd/system/docker.service
--13行--修改
ExecStart=/usr/bin
/dockerd -H unix:///var/run/docker.sock -H tcp://192.168.80.10:2375
(2)重啟 Docker
systemctl daemon-reload
systemctl restart docker
netstat -natp | grep 2375
(3)在宿主機(jī)的 firewalld 上做 IP 訪問控制,source address 指定的是客戶端地址
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.80.15" port protocol="tcp" port="2375" accept"
firewall-cmd --reload
或
iptables -t filter -A INPUT -s 192.168.80.15 -p tcp --dport 2375 -j ACCEPT
(4)在客戶端上實(shí)現(xiàn)遠(yuǎn)程授權(quán)訪問
docker -H tcp://192.168.80.10 images
限制流量流向
//使用防火墻過濾器限制 Docker 容器的源 IP 地址范圍與外界通訊。
firewall-cmd --permanent --zone=public --add-rich-rule=“rule family=“ipv4” source address=“192.168.80.0/24” reject”
iptables -t filter -A INPUT -s 192.168.80.0/24 -j REJECT
//生產(chǎn)環(huán)境中的大量問題是因?yàn)?Docker 容器端口外放引起的漏洞,除了操作系統(tǒng)賬戶權(quán)限控制上的問題,更在于對(duì) Docker Daemon 的進(jìn)程管理上存在隱患。
目前常用的 Docker 版本都支持 Docker Daemon 管理宿主機(jī) iptables 的,而且一旦啟動(dòng)進(jìn)程加上 -p host_port:guest_port 的端口映射,Docker Daemon 會(huì)直接增加對(duì)應(yīng)的 FORWARD Chain 并且 -j ACCEPT,而默認(rèn)的 DROP 規(guī)則是在 INPUT 鏈做的,對(duì) docker 沒法限制,這就留下了很嚴(yán)重的安全隱患。因此建議:
(1)不在有外網(wǎng) ip 的機(jī)器上使用 Docker 服務(wù)。
(2)使用 k8s 等 docker 編排系統(tǒng)管理 Docker 容器。
(3)宿主機(jī)上 Docker daemon 啟動(dòng)命令加一個(gè) --iptables=false,然后把常用 iptables 規(guī)則寫進(jìn)文件里,再用 iptables-restore 重定向輸入去刷新規(guī)則。
鏡像安全
一般情況下,要確保只從受信任的庫(kù)中獲取鏡像,推薦使用 harbor 私有倉(cāng)庫(kù)。
如果公司使用的不是自己的鏡像源,需要使用 Docker 鏡像安全掃描工具 Clair,對(duì)下載的鏡像進(jìn)行檢查。通過與 CVE 數(shù)據(jù)庫(kù)同步掃描鏡像,驗(yàn)證鏡像的 md5 等特征值,確認(rèn)一致后再基于鏡像進(jìn)一步構(gòu)建。一旦發(fā)現(xiàn)漏洞則通知用戶處理, 或者直接阻止鏡像繼續(xù)構(gòu)建。
避免Docker 容器中信息泄露
近幾年 Github 上大量泄露個(gè)人或企業(yè)各種賬號(hào)密碼,出現(xiàn)這種問題一般都使用 dockerfile 或者 docker-compose 文件創(chuàng)建容器。 如果這些文件中存在賬號(hào)密碼等認(rèn)證信息,一旦 Docker 容器對(duì)外開放,則這些宿主機(jī)上的敏感信息也會(huì)隨之泄露。
DockerClient 端與 DockerDaemon 的通信安全
為了防止鏈路劫持、會(huì)話劫持等問題導(dǎo)致 Docker 通信時(shí)被中間人攻擊,c/s 兩端應(yīng)該通過 TLS 加密方式通訊。
通過在服務(wù)端上創(chuàng)建tls密鑰證書,再下發(fā)給客戶端,客戶端通過私鑰訪問容器,這樣就保證的docker通訊的安全性。
//使用證書訪問的工作流程:
(1)客戶端發(fā)起HTTPS請(qǐng)求,連接到服務(wù)器的443端口。
(2)服務(wù)器必須要先申請(qǐng)好一套數(shù)字證書(證書內(nèi)容有公鑰、證書頒發(fā)機(jī)構(gòu)、失效日期等)。
(3)服務(wù)器將自己的數(shù)字證書發(fā)送給客戶端(公鑰在證書里面,私鑰由服務(wù)器持有)。
(4)客戶端收到數(shù)字證書之后,會(huì)先驗(yàn)證證書的合法性。如果證書驗(yàn)證通過,就會(huì)使用偽隨機(jī)數(shù)生成器(/dev/random)隨機(jī)生成一個(gè)【對(duì)稱密鑰】,使用證書的公鑰加密這個(gè)【對(duì)稱密鑰】。
(5)客戶端將公鑰加密后的【對(duì)稱密鑰】發(fā)送到服務(wù)器。
(6)服務(wù)器接收到客戶端發(fā)來(lái)的密文密鑰之后,用自己之前保留的私鑰對(duì)其進(jìn)行非對(duì)稱解密,解密之后就得到客戶端的【對(duì)稱密鑰】,然后用客戶端的【對(duì)稱密鑰】對(duì)返回?cái)?shù)據(jù)進(jìn)行加密,這樣傳輸?shù)臄?shù)據(jù)都是密文了。
(7)服務(wù)器將加密后的密文數(shù)據(jù)返回到客戶端。
(8)客戶端收到后,用自己的【對(duì)稱密鑰】對(duì)其進(jìn)行對(duì)稱解密,得到服務(wù)器返回的數(shù)據(jù)。
首先創(chuàng)建ca證書,ca證書只是一個(gè)官方認(rèn)證的證書,接下來(lái)要?jiǎng)?chuàng)建server、client節(jié)點(diǎn)的證書。
此時(shí)創(chuàng)建證書有三步:
(1)設(shè)置私鑰,確保安全加密
(2)使用私鑰簽名,確保身份真實(shí)不可抵賴
(3)使用ca證書制作證書
master 192.168.80.10 docker-ce-cli-20.10.5-3.el7.x86_64 docker-ce
client 192.168.80.15 docker-ce-cli-20.10.5-3.el7.x86_64 docker-ce
注:由于 20.10.9 版本的 docker 客戶端用的 go 版本是 go1.16.8,而 go1.15 以后的版本不支持私有 CA 生成的證書,所以這里 docker 客戶端仍使用 docker-ce-cli-20.10.5-3.el7.x86_64 安裝的版本。
//首先創(chuàng)建一個(gè)存放目錄
mkdir /tls
cd /tls/
//生成ca證書
(1)創(chuàng)建ca私鑰
openssl genrsa -aes256 -out ca-key.pem 4096 #輸入123123
genrsa:使用RSA算法產(chǎn)生私鑰
-aes256:使用256位密鑰的AES算法對(duì)私鑰進(jìn)行加密,這樣每次使用私鑰文件都將輸入密碼,可省略
-out:輸出文件的路徑,若未指定輸出文件,則為標(biāo)準(zhǔn)輸出
4096:指定私鑰長(zhǎng)度,默認(rèn)為1024。該項(xiàng)必須為命令行的最后一項(xiàng)參數(shù)
(2)創(chuàng)建ca證書
openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj “/CN=*” -out ca.pem
req:執(zhí)行證書簽發(fā)命令
-new:新證書簽發(fā)請(qǐng)求
-x509:生成x509格式證書,專用于創(chuàng)建私有CA時(shí)使用
-days:證書的有效時(shí)長(zhǎng),單位是天
-key:指定私鑰路徑
-sha256:證書摘要采用sha256算法
-subj:證書相關(guān)的用戶信息(subject的縮寫)
-out:輸出文件的路徑
//用 ca 證書簽發(fā) server 端證書
(3)創(chuàng)建服務(wù)器私鑰
openssl genrsa -out server-key.pem 4096
(4)生成證書簽名請(qǐng)求文件(csr文件)
openssl req -new -key server-key.pem -sha256 -subj “/CN=*” -out server.csr
(5)使用ca 證書與私鑰證書簽發(fā)服務(wù)端簽名證書,輸入 123123,(需要簽名請(qǐng)求文件,ca 證書,ca 密鑰)
openssl x509 -req -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -days 1000 -out server-cert.pem文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-609257.html
x509:生成x509格式證書
-req:輸入csr文件
-in:要輸入的csr文件
-CA:指定ca證書的路徑
-CAkey:指定ca證書的私鑰路徑
-CAcreateserial:表示創(chuàng)建證書序列號(hào)文件,創(chuàng)建的序列號(hào)文件默認(rèn)名稱為ca.srl文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-609257.html
//用ca證證書簽發(fā)client端證書
(6)生成客戶端私鑰
openssl genrsa -out client-key.pem 4096
(7)生成證書簽名請(qǐng)求文件
openssl req -new -key client-key.pem -subj "/CN=client" -out client.csr
(8)創(chuàng)建擴(kuò)展配置文件,使秘鑰適合客戶端身份驗(yàn)證
echo extendedKeyUsage=clientAuth > extfile.cnf
(9)使用 ca 證書簽發(fā)客戶端簽名證書,輸入 123123,(需要簽名請(qǐng)求文件,ca 證書,ca 密鑰)
openssl x509 -req -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -extfile extfile.cnf -days 1000 -out client-cert.pem
//刪除兩個(gè)證書簽名請(qǐng)求文件和擴(kuò)展配置文件
rm -rf ca.srl client.csr extfile.cnf server.csr
//配置docker服務(wù)配置文件
vim /lib/systemd/system/docker.service
--13行--修改
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/tls/ca.pem --tlscert=/tls/server-cert.pem --tlskey=/tls/server-key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock
//重啟docker服務(wù)
systemctl daemon-reload
systemctl restart docker
netstat -natp | grep 2376
setenforce 0
//將 /tls 目錄中的 ca.pem、client-cert.pem、client-key.pem 三個(gè)文件復(fù)制到另一臺(tái)主機(jī)
scp ca.pem root@192.168.80.10:/etc/docker/
scp client-cert.pem root@192.168.80.10:/etc/docker/
scp client-key.pem root@192.168.80.10:/etc/docker/
//本地驗(yàn)證,使用證書訪問時(shí)要用主機(jī)名連接,docker 不支持使用 IP 進(jìn)行證書訪問
hostnamectl set-hostname master
su
vim /etc/hosts
127.0.0.1 master
docker --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H tcp://master:2376 images
//在客戶端上操作
hostnamectl set-hostname client
su
vim /etc/hosts
192.168.80.10 master
cd /etc/docker/
docker --tlsverify --tlscacert=ca.pem --tlscert=client-cert.pem --tlskey=client-key.pem -H tcp://master:2376 images
到了這里,關(guān)于[ 容器 ] Docker 安全及日志管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!