Docker 容器與虛擬機的區別
1.隔離與共享
虛擬機經過添加 Hypervisor 層,虛擬出網卡、內存、CPU 等虛擬硬件,再在其上創建 虛擬機,每一個虛擬機都有本身的系統內核。
而 Docker 容器則是經過隔離的方式,將文件系 統、進程、設備、網絡等資源進行隔離,再對權限、CPU 資源等進行控制,最終讓容器之間互不影響,
容器沒法影響宿主機。容器與宿主機共享內核、文件系統、硬件等資源。
2.性能與損耗
與虛擬機相比,容器資源損耗要少。 一樣的宿主機下,可以創建容器的數量要比虛擬 機多。可是,虛擬機的安全性要比容器稍好,
要從虛擬機攻破到宿主機或其餘虛擬機,須要 先攻破 Hypervisor 層,這是極其困難的。而 docker 容器與宿主機共享內核、文件系統等資源,
更有可能對其餘容器、宿主機產生影響。
Docker 存在的安全問題
1.Docker 自身漏洞
做爲一款應用 Docker 自己實現上會有代碼缺陷。CVE官方記錄Docker歷史版本共有超過20項漏洞。
經常使用的手段主要有代碼執行、權限提高、 信息泄露、權限繞過等。目前 Docker 版本更迭很是快,
Docker 用戶最好將 Docker 升級爲 最新版本。
linux
- Docker 源碼問題
Docker 提供了 Docker hub,可讓用戶上傳建立的鏡像,以便其餘用戶下載,快速搭 建環境。但同時也帶來了一些安全問題。例以下面三種方式:
(1)上傳惡意鏡像 若是有在製做的鏡像中植入、後門等惡意軟件,那麼環境從一開始就已經不安全了,後續更沒有什麼安全可言。
(2)鏡像使用有漏洞的軟件 Docker Hub 上能下載的鏡像裏面,75%的鏡像都安裝了有漏洞的軟件。因此下載鏡像後,
須要檢查裏面軟件的版本信息,對應的版本是否存在漏洞,並及時更新打上補丁。
(3)中間人
篡改鏡像 鏡像在傳輸過程當中可能被篡改,目前新版本的 Docker 已經提供了相應的校驗機制來預 防這個問題。
Docker 架構缺陷與安全機制
Docker 自己的架構與機制就可能產生問題,例如這樣一種場景已經控制了宿主機上的一些容器,或者得到了經過在公有云上創建容器的方式,而後對宿主機或其餘容器發起。 - 容器之間的局域網**
主機上的容器之間能夠構成局域網,所以針對局域網的 ARP 欺騙、嗅探、廣播風暴等攻 擊方式即可以用上。
因此,在一個主機上部署多個容器須要合理的配置網絡,設置 iptable 規則。 - DDoS 耗盡資源
Cgroups 安全機制就是要防止此類的,不要爲單一的容器分配過多的資源便可避免此類問題。 - 有漏洞的系統調用
Docker與虛擬機的一個重要的區別就是Docker與宿主機共用一個操做系統內核。
一旦宿主內核存在能夠越權或者提權漏洞,儘管Docker使用普通用戶執行,在容器被gj時,者還能夠利用內核漏洞跳到宿主機作更多的事情。 - 共享root用戶權限
若是以 root 用戶權限運行容器,容器內的 root 用戶也就擁有了宿主機的root權限。
Docker 安全基線標準
下面從內核、主機、網絡、鏡像、容器以及其它等 6 個方 面總結 Docker 安全基線標準。
1.內核級別
(1)及時更新內核。
(2)User NameSpace(容器內的 root 權限在容器以外處於非高權限狀態)。
(3)Cgroups(對資源的配額和度量)。
(4)SELiux/AppArmor/GRSEC(控制文件訪問權限)。
(5)Capability(權限劃分)。
(6)Seccomp(限定系統調用)。
(7)禁止將容器的命名空間與宿主機進程命名空間共享。
2.主機級別
(1)爲容器建立獨立分區。
(2)僅運行必要的服務。
(3)禁止將宿主機上敏感目錄映射到容器。
(4)對 Docker 守護進程、相關文件和目錄進行審計。
(5)設置適當的默認文件描述符數。
(文件描述符:內核(kernel)利用文件描述符(file descriptor)來訪問文件。文件描述符是非負整數。
打開現存文件或新建文件時,內核會返回一個文件描述符。讀寫文件也須要使用文件描述符來指定待讀寫的文件)
(6)用戶權限爲 root 的 Docker 相關文件的訪問權限應該爲 644 或者更低權限。
(7)週期性檢查每一個主機的容器清單,並清理沒必要要的容器。
3.網絡級別
(1)經過 iptables 設定規則實現禁止或容許容器之間網絡流量。
(2)容許 Dokcer 修改 iptables。
(3)禁止將 Docker 綁定到其餘 IP/Port 或者 Unix Socket。
(4)禁止在容器上映射特權端口。
(5)容器上只開放所須要的端口。
(6)禁止在容器上使用主機網絡模式。
(7)若宿主機有多個網卡,將容器進入流量綁定到特定的主機網卡上。
4.鏡像級別
(1)建立本地鏡像倉庫服務器。
(2)鏡像中軟件都爲最新版本。
(3)使用可信鏡像文件,並經過安全通道下載。
(4)從新構建鏡像而非對容器和鏡像打補丁。
(5)合理管理鏡像標籤,及時移除再也不使用的鏡像。
(6)使用鏡像掃描。
(7)使用鏡像簽名。
5.容器級別
(1)容器最小化,操做系統鏡像最小集。
(2)容器以單一主進程的方式運行。
(3)禁止 privileged 標記使用特權容器。
(4)禁止在容器上運行 ssh 服務。
(5)以只讀的方式掛載容器的根目錄系統。
(6)明肯定義屬於容器的數據盤符。
(7)經過設置 on-failure 限制容器嘗試重啓的次數,容器反覆重啓容易丟失數據。
(8)限制在容器中可用的進程樹,以防止 fork bomb。(fork炸彈,迅速增加子進程,耗盡系統進程數量)
6.其餘設置
(1)按期對宿主機系統及容器進行安全審計。
(2)使用最少資源和最低權限運行容器。
(3)避免在同一宿主機上部署大量容器,維持在一個可以管理的數量。
(4)監控 Docker 容器的使用,性能以及其餘各項指標。
(5)增長實時威脅檢測和事件響應功能。
(6)使用中心和遠程日誌收集服務
容器最小化
若是僅在容器中運行必要的服務,像 SSH 等服務是不能輕易開啓去鏈接容器的。一般使用如下方式來進入容器。docker exec -it a661258f6bfe bash
Docker remote api 訪問控制
Docker的遠程調用 API 接口存在未受權訪問漏洞,至少應限制外網訪問。建議使用 Socket 方式訪問。
監聽內網 ip,docker daemon 啓動方式以下。
nginxdocker -d -H uninx:///var/run/docker.sock -H tcp://192.168.191.132:2375 或者 vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://192.168.195.128:2375 systemctl daemon-reload systemctl restart docker
而後,在宿主機的 firewalld 上作 IP 訪問控制便可。(source address 是客戶端地址)docker
//在其餘節點訪問docker狀態 [root@localhost ~]# docker -H=tcp://192.168.191.132:2375 ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
限制流量流向
使用防火牆過濾器限制 Docker 容器的源 IP 地址範圍與外界通信。
數據庫firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.195.0/24" reject"
大量問題是由於Docker容器端口外放引發的漏洞,除了操做系統帳戶權限控制上的問題,更在於對Docker Daemon的進程管理上存在隱患。
目前經常使用的Docker版本都支持Docker Daemon管理宿主iptables的,並且一旦啓動進程加上-p host_port:guest_port的端口映射,
Docker Daemon會直接增長對應的FORWARD Chain而且-j ACCEPT,而默認的DROP規則是在INPUT鏈作的,對docker無法限制,
這就留下了很嚴重的安全隱患了。所以建議:
vim- 不在有外網ip的機器上使用Docker服務
- 使用k8s等docker編排系統管理Docker容器
- 宿主上Docker daemon啓動命令加一個--iptables=false,而後把經常使用iptables寫進文件裏,再用iptables-restore去刷。
鏡像安全
Docker 鏡像安全掃描,在鏡像倉庫客戶端使用證書認證,對下載的鏡像進行檢查。
經過與 CVE 數據庫同步掃描鏡像,一旦發現漏洞則通知用戶處理,或者直接阻止鏡像繼續構建。
Docker-TLS加密通信
爲了防止鏈路劫持、會話劫持等問題致使 Docker 通訊時被中 間人***,c/s 兩端應該經過加密方式通信。[root@localhost ~]mkdir /tls [root@localhost ~]cd /tls [root@localhost ~]hostnamectl set-hostname master [root@localhost ~]su [root@master ~]
[root@master ~]vim /etc/hosts 127.0.0.1 master //建立ca密鑰 openssl genrsa -aes256 -out ca-key.pem 4096 //輸入123123 //建立ca證書 openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem //輸入123123 //建立服務器私鑰 openssl genrsa -out server-key.pem 4096 //簽名私鑰 openssl req -subj "/CN=*" -sha256 -new -key server-key.pem -out server.csr //使用ca證書與私鑰證書籤名,輸入123123 openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
//生成客戶端密鑰 openssl genrsa -out key.pem 4096 //簽名客戶端 openssl req -subj "/CN=client" -new -key key.pem -out client.csr //建立配置文件 echo extendedKeyUsage=clientAuth > extfile.cnf //簽名證書,輸入123123,須要(簽名客戶端,ca證書,ca密鑰) openssl x509 -req -days 1000 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf //刪除多餘文件 rm -rf ca.srl client.csr extfile.cnf server.csr //配置docker vim /lib/systemd/system/docker.service 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
//重啓進程 systemctl daemon-reload //重啓docker服務 systemctl restart docker //將 /tls/ca.pem /tls/cert.pem /tls/key.pem 三個文件複製到另外一臺主機 scp ca.pem root@192.168.191.132:/etc/docker/ scp cert.pem root@192.168.191.132:/etc/docker/ scp key.pem root@192.168.191.132:/etc/docker/ //本地驗證 docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H tcp://master:2376 version docker pull nginx
//client上操做 [root@master ~]vim /etc/hosts 192.168.191.132 master docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H tcp://master:2376 version Client: Docker Engine - Community Version: 19.03.5 API version: 1.40 Go version: go1.12.12 Git commit: 633a0ea Built: Wed Nov 13 07:25:41 2019 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.5 API version: 1.40 (minimum version 1.12) Go version: go1.12.12 Git commit: 633a0ea Built: Wed Nov 13 07:24:18 2019 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.10 GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339 runc: Version: 1.0.0-rc8+dev GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 docker-init: Version: 0.18.0 GitCommit: fec3683