在docker中運行第三方服務時,通常需要綁定服務端口到本地主機。但使用 -p 參數進行的端口映射,會自動在iptables中建立規則,繞過firewalld,這對於端口級的黑白名單控制管理是很不利的,所以我們需要對iptables進行手動修改。
這里以從名為centos.19.09.05的image建立一個容器為例:
首先,如果系統是CentOS7的話,需要關閉自帶firewalld防火牆,並切換為iptables.
假設需要將新容器的27017端口映射到主機的27017端口,一般情況下我們使用命令
docker run -idt -p 27017:27017 centos.19.09.05 /bin/bash
在容器中27017端口服務運行起來后,我們在外網使用端口掃描工具,發現本地主機的27017端口已經打開了,而我們還未在防火牆上進行開放操作;此時檢查iptabes規則:
iptables --list
發現在Chain DOCKER下多出了一條
Chain DOCKER (1 references) target prot opt source destination ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:27017
其中172.17.0.2為該容器在docker網橋中的IP,可見該規則允許任意來源的地址訪問27017端口,所以我們需要刪除該規則,並替換成安全性更高的規則。
#刪除DOCKER鏈中的1號規則;如果待刪除規則不位於第一行,則將數字改為對應行號 iptables -D DOCKER 1 #此容器只接受來自地址123.345.456.567的連接請求 iptables -A DOCKER -s 123.345.456.567 -d 172.17.0.2 -p tcp --sport 27017 -j ACCEPT
再次進行端口掃描,發現27017端口已經關閉,只有IP為123.234.345.456的主機能夠連接。
還有一種更簡單的方式。因為docker繞過防火牆的原理是修改了iptables,那不讓它修改即可,此方法無需切換默認防火牆。
按照https://blog.csdn.net/qadzhangc/article/details/96140703 所述設置即可,經試驗不可省略步驟,否則可能造成容器無法連接外網。
vim /etc/default/docker #修改文件,此處設置等同於在創建容器時手動指定iptables=false參數 DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 -iptables=false"
vim /etc/docker/daemon.json { "iptables": false }
#此處對更改設置之前創建的容器也有效,編輯后需重啟docker服務
對ufw的設置主要是為容器建立起轉發,如果容器內的服務不需要訪問外網,不做也可以。
firewalld的操作與ufw有些不同
#ubuntu(ufw)操作為 vim /etc/default/ufw DEFAULT_FORWARD_POLICY="ACCEPT" #對應centos(firewalld)上操作為: firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 0 -i eth0 -j ACCEPT #eth0為宿主機網卡名 firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 0 -o eth0 -j ACCEPT firewall-cmd --reload
ubuntu(ufw): vim /etc/ufw/before.rules 在`*filter`前面添加下面內容 *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE COMMIT centos(firewalld): firewall-cmd --zone=public --add-masquerade #默認docker0在public zone里 firewall-cmd --reload