docker需不需要防火墻軟件奶赠?
其實(shí)這個(gè)問(wèn)題之前一直困擾著我踩娘,在請(qǐng)教技術(shù)大牛以及自己探討以后娘荡,得到了一個(gè)答案搔谴,那就是docker不需要防火墻軟件(注意這里指的是firewalld魁袜,iptables等防火墻軟件而不是iptables服務(wù))。
防火墻軟件是否對(duì)docker有影響敦第?
docker引擎啟動(dòng)的時(shí)候會(huì)修改iptables規(guī)則峰弹,如果使用了防火墻軟件,只要重啟防火墻軟件芜果,則docker的規(guī)則就全部丟失鞠呈,影響容器訪問(wèn)。
如果必須使用防火墻需要注意什么右钾?
增刪開(kāi)放端口都必須通過(guò)動(dòng)態(tài)命令添加蚁吝,并且不應(yīng)該重啟防火墻。
如果使用防火墻霹粥,部署業(yè)務(wù)映射了宿主機(jī)的端口灭将,是否應(yīng)該開(kāi)放該端口?
沒(méi)有必要后控,因?yàn)椴还苣汩_(kāi)不開(kāi)放端口庙曙,都可以訪問(wèn)到服務(wù)。具體看下面的解釋浩淘。
Docker網(wǎng)絡(luò)模式
Docker有多中網(wǎng)絡(luò)模式捌朴,包括host,none,bridge ,overlay等张抄。下面以Docker默認(rèn)的bridge網(wǎng)絡(luò)---Docker0來(lái)探討Docker網(wǎng)絡(luò)與iptables的關(guān)系砂蔽。
Docker0網(wǎng)絡(luò)是Docker搭建的一個(gè)虛擬橋接網(wǎng)絡(luò),默認(rèn)網(wǎng)關(guān)地址是172.17.0.1署惯。Docker默認(rèn)的網(wǎng)絡(luò)是Docker0網(wǎng)絡(luò)左驾,也就意味著Docker中所有沒(méi)有指定網(wǎng)絡(luò)的容器都會(huì)加入到這個(gè)橋接網(wǎng)絡(luò)中,網(wǎng)絡(luò)中的容器可以互相通信。
# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:c0ff:febb:bb1e
容器對(duì)外請(qǐng)求數(shù)據(jù)
如果Docker0中的容器請(qǐng)求外部的數(shù)據(jù)诡右,那么他的數(shù)據(jù)包將會(huì)發(fā)送到網(wǎng)關(guān)172.17.0.1處安岂。當(dāng)數(shù)據(jù)包到達(dá)網(wǎng)關(guān)后,將會(huì)查詢主機(jī)的路由表帆吻,確定數(shù)據(jù)包將從那個(gè)網(wǎng)卡發(fā)出域那。iptables負(fù)責(zé)對(duì)數(shù)據(jù)包進(jìn)行snat轉(zhuǎn)換,將原地址轉(zhuǎn)為對(duì)應(yīng)網(wǎng)卡的地址猜煮,因此容器對(duì)外是不可見(jiàn)的次员。
外部對(duì)容器請(qǐng)求數(shù)據(jù)
外部想要訪問(wèn)容器內(nèi)的數(shù)據(jù),首先需要將容器的端口映射到宿主機(jī)上王带。這時(shí)候docker會(huì)在iptables添加轉(zhuǎn)發(fā)規(guī)則淑蔚,把接收到的數(shù)據(jù)轉(zhuǎn)發(fā)給容器。
Docker數(shù)據(jù)在iptables中傳遞
下圖是數(shù)據(jù)包在iptable的傳遞流程
創(chuàng)建一個(gè)端口映射的容器
接下來(lái)我們查看一下容器數(shù)據(jù)包在iptable中怎么傳遞的 創(chuàng)建一個(gè)redis容器辫秧,將映射容器6379端口到宿主機(jī)36379端口束倍。
# docker run --name redistest -d -p 36379:6379 172.16.1.129/redis/3.0.7:v1.1
b4c3fc06cdaccc2080f9e4845ebb2d2b789632ddaecb6e7b2e3bdf863c416014
查看iptables的nat表
# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere !loopback/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
CATTLE_NAT_POSTROUTING all -- anywhere anywhere
MASQUERADE all -- 172.17.0.0/16 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:6379
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN all -- anywhere anywhere
DNAT tcp -- anywhere anywhere tcp dpt:36379 to:172.17.0.3:6379
可以看到iptables的nat表中有一條Docker子鏈 里面有一條數(shù)據(jù)
DNAT tcp -- anywhere anywhere tcp dpt:36379 to:172.17.0.3:6379
這條數(shù)據(jù)就是負(fù)責(zé)宿主機(jī)tcp36379端口映射到172.17.0.3:6379上。
Docker子鏈被PREROUTING和OUTPUT鏈引用
PREROUTING:數(shù)據(jù)包到達(dá)防火墻時(shí)改變包的目的地址
OUTPUT:過(guò)濾所有本機(jī)產(chǎn)生的數(shù)據(jù)包(對(duì)源地址得數(shù)據(jù)包的過(guò)濾)
也就是說(shuō)外部對(duì)宿主機(jī)36379訪問(wèn)的數(shù)據(jù)包在nat這里被進(jìn)行snat和pnat轉(zhuǎn)換盟戏,目的地址轉(zhuǎn)為172.17.0.3:6379绪妹。
容器對(duì)外部訪問(wèn)的數(shù)據(jù)包也在這里進(jìn)行dnat和pnat,將172.17.0.3:6379轉(zhuǎn)為宿主機(jī)的36379端口
查看iptables的filter表
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-ISOLATION all -- anywhere anywhere
DOCKER all -- anywhere anywhere
DROP all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.3 tcp dpt:6379
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
里面同樣有一個(gè) DOCKER子鏈柿究,被FORWARD鏈引用
- FORWARD鏈:過(guò)濾所有路過(guò)本機(jī)的數(shù)據(jù)包(源地址和目標(biāo)地址都不是本機(jī)的數(shù)據(jù)包)
也就是說(shuō)經(jīng)過(guò)nat切換地址以后邮旷,測(cè)試容器的數(shù)據(jù)包將會(huì)轉(zhuǎn)發(fā)到172.17.0.3,而不是宿主機(jī),過(guò)濾規(guī)則是Accept蝇摸,也就是通過(guò)婶肩。
通過(guò)上面的分析,可以知道數(shù)據(jù)到達(dá)宿主機(jī)的防火墻貌夕,直接就forward到容器了律歼,沒(méi)有執(zhí)行到input流程,所以容器映射的宿主機(jī)端口不需要開(kāi)放啡专。
docker與防火墻軟件同時(shí)使用注意事項(xiàng)
docker的部分網(wǎng)絡(luò)功能是通過(guò)iptables轉(zhuǎn)發(fā)來(lái)完成的险毁,轉(zhuǎn)發(fā)規(guī)則是docker進(jìn)程啟動(dòng)后動(dòng)態(tài)添加的,也就意味著如果你重啟iptables们童,將會(huì)丟失docker的轉(zhuǎn)發(fā)規(guī)則畔况。
有兩種解決辦法:
- 動(dòng)態(tài)添加iptables規(guī)則,然后保存到防火墻軟件配置文件中
動(dòng)態(tài)添加iptables規(guī)則可以使規(guī)則立即生效(重啟失效)
sudo iptables -I INPUT 1 -p tcp --dport 46379 -j ACCEPT
這條命令會(huì)將規(guī)則添加到input規(guī)則的第一位 ,-I參數(shù)指定插入位置慧库。不要使用-A參數(shù)跷跪,該參數(shù)會(huì)將規(guī)則添加到input的最后一條,一般原來(lái)的最后一條都是reject規(guī)則齐板,所以新插入的規(guī)則無(wú)法生效吵瞻。
sudo service iptables save
- 重啟iptable后重新啟動(dòng)docker
影響:重啟docker會(huì)導(dǎo)致全部容器重啟葛菇,有可能造成短時(shí)間的業(yè)務(wù)故障。
此方法不建議使用橡羞,如果已經(jīng)重啟防火墻熟呛,導(dǎo)致docker業(yè)務(wù)故障,使用下面命令重啟dcoker尉姨。
systemctl restart docker