防火墻控制Docker端口開放與關閉
問題描述
docker下的oracle數據庫服務存在漏洞,解決難度較高,于是通過firewalld限制高危端口開放,只允許本機訪問。發(fā)現(xiàn)即使配置規(guī)則firewalld把oracle 1521漏洞端口不開放出去,但其他服務器依然能訪問這給服務器的1521端口,也就是說firewalld配置的規(guī)則失效。
第一種方案
docker容器在創(chuàng)建時會在iptables的INPUT表的DOCKER鏈下自動創(chuàng)建規(guī)則放行端口,為了保證docker啟動的每一個容器都能被外界訪問(自私!),所以導致firewalld不放行端口也能被外界訪問。
Firewalld服務啟動時,會將iptables上的規(guī)則全部清空,并把firewalld上的防火墻策略規(guī)則寫入到iptables中,此時docker因為防火墻規(guī)則被刪除就會不正常,需要重啟systemctl restart docker服務來重新刷寫防火墻規(guī)則到iptables上,所以我們在管理Docker端口時,應該使用iptables防火墻而不是firewalld防火墻服務
首先在docker容器啟動時不讓它自動在iptables上船艦規(guī)則,在docker配置文件中添加 “iptables”: false
[root@localhost ~]# vi /etc/docker/daemon.json { "data-root": "/opt/docker", "iptables": false } #重啟生效 [root@localhost ~]# systemctl daemon-reload [root@localhost ~]# systemctl restart docker
此時我們就可以隨便關閉我們不想放行的端口了,做到使用iptables管理Docker容器端口。
引發(fā)問題
發(fā)現(xiàn)以上做法可以屏蔽端口了,但是出現(xiàn)容器不能與宿主機其他服務器通訊,原因是加入了 “iptables”: false后,不能在iptables添加任何規(guī)則了,正常來說docker啟動時不止是添加幾條容器端口開放這么簡單,docker容器啟動時還需要在nat表添加-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE這些規(guī)則,這些規(guī)則是處理docker的SNAT地址偽裝用的,直白來說就是用來容器內部訪問外部網絡的。具體含義是將容器網絡網段發(fā)送到外部的數據包(! -o docker0)偽裝成宿主機的ip,就是將數據包的原來的容器ip換成了宿主機ip做了一次snat,沒經過源IP地址轉換是不能正常通訊的。
#網絡不通 [root@localhost ~]# docker exec -it tomcat bash root@b287f29a1b60:/usr/local/tomcat# ping 172.21.36.43 #另一臺宿主機IP PING 172.21.36.43 (172.21.36.43) 56(84) bytes of data. ^C --- 172.21.36.43 ping statistics --- 8 packets transmitted, 0 received, 100% packet loss, time 9ms #iptables規(guī)則消失 [root@localhost ~]# iptables -nL Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
解決方法:
在docker啟動配置中加入配置
vi /etc/systemd/system/docker.service [Service] ExecStartPre=/usr/sbin/iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE ExecStopPost=/usr/sbin/iptables -t nat -D POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE #加載并重啟docker systemctl daemon-reload systemctl restart docker
#172.17.0.0/16 IP為容器的IP網段,查看容器的IP網段,需要查看容器的網絡模式,沒指定的話一般為bridge
如果容器里使用了不同的網絡,每個網絡都要開放,沒有開放的網絡不能與外網通訊
問題解決,
不過iptables -I INPUT -p tcp --dport 1521 -j DROP
加入這條規(guī)制,本地也無法通過IP訪問,所以容器內部要么通過容器名相互訪問,要么再加一條允許本地IP訪問策略
iptables -I INPUT -s 172.21.36.67 -t tcp -j ACCEPT
第二種方案
以至于后來我才發(fā)現(xiàn)第二種解決辦法,看了第二種方案你就會覺得第一種方案有多傻,我們要實現(xiàn)防火墻管理Docker端口,只需要在iptables的filter表的DOCKER-USER鏈下添加規(guī)則即可。
#只允許10.108.11.178訪問容器的1521端口 [root@data dciproject]# iptables -I DOCKER-USER ! -s 10.108.11.178 -p tcp --dport 1521 -j DROP [root@data dciproject]# iptables -nL Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9090 ACCEPT tcp -- 10.108.11.178 0.0.0.0/0 tcp dpt:1521 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8091 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8085 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9695 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:7001 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8086 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8083 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8089 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:19080 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8088 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:445 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:139 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22223 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:7443 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:7010 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:10020 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:10010 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6443 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6080 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5432 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:9011 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8082 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8081 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:1521 Chain FORWARD (policy ACCEPT) target prot opt source destination DOCKER-USER all -- 0.0.0.0/0 0.0.0.0/0 DOCKER-ISOLATION-STAGE-1 all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (5 references) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 10.1.1.2 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 192.168.0.2 tcp dpt:5000 ACCEPT tcp -- 0.0.0.0/0 10.1.0.2 tcp dpt:9090 ACCEPT tcp -- 0.0.0.0/0 10.1.3.2 tcp dpt:5432 ACCEPT tcp -- 0.0.0.0/0 10.1.1.3 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.1.3 tcp dpt:1521 ACCEPT tcp -- 0.0.0.0/0 10.1.0.3 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 192.168.0.3 tcp dpt:8085 ACCEPT tcp -- 0.0.0.0/0 192.168.0.3 tcp dpt:80 ACCEPT tcp -- 0.0.0.0/0 10.1.0.4 tcp dpt:5432 ACCEPT tcp -- 0.0.0.0/0 10.1.1.4 tcp dpt:15675 ACCEPT tcp -- 0.0.0.0/0 10.1.1.4 tcp dpt:15672 ACCEPT tcp -- 0.0.0.0/0 10.1.1.4 tcp dpt:5672 ACCEPT tcp -- 0.0.0.0/0 10.1.1.4 tcp dpt:1883 ACCEPT tcp -- 0.0.0.0/0 10.1.1.5 tcp dpt:6379 ACCEPT tcp -- 0.0.0.0/0 10.1.1.6 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.0.6 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.1.7 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.1.8 tcp dpt:19080 ACCEPT tcp -- 0.0.0.0/0 10.1.0.8 tcp dpt:9191 ACCEPT tcp -- 0.0.0.0/0 10.1.0.8 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.1.9 tcp dpt:27017 ACCEPT tcp -- 0.0.0.0/0 10.1.0.9 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.0.11 tcp dpt:8000 ACCEPT tcp -- 0.0.0.0/0 10.1.0.12 tcp dpt:8080 ACCEPT tcp -- 0.0.0.0/0 10.1.0.13 tcp dpt:5432 Chain DOCKER-ISOLATION-STAGE-1 (1 references) target prot opt source destination DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0 DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0 DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0 DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0 DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0 RETURN all -- 0.0.0.0/0 0.0.0.0/0 Chain DOCKER-ISOLATION-STAGE-2 (5 references) target prot opt source destination DROP all -- 0.0.0.0/0 0.0.0.0/0 DROP all -- 0.0.0.0/0 0.0.0.0/0 DROP all -- 0.0.0.0/0 0.0.0.0/0 DROP all -- 0.0.0.0/0 0.0.0.0/0 DROP all -- 0.0.0.0/0 0.0.0.0/0 RETURN all -- 0.0.0.0/0 0.0.0.0/0 Chain DOCKER-USER (1 references) target prot opt source destination DROP tcp -- !10.108.11.178 0.0.0.0/0 tcp dpt:1521 RETURN all -- 0.0.0.0/0 0.0.0.0/0 Chain l (0 references) target prot opt source destination [root@data dciproject]#
#永久保存iptables規(guī)則 [root@data dciproject]# yum install iptables -y && yum install iptables-services -y [root@data dciproject]# systemctl start iptables.service && systemctl enable iptables.service [root@data dciproject]# service iptables save
在docjer啟動的時創(chuàng)建的眾多鏈中,DOCKER-USER鏈優(yōu)先級最高,用于自定義轉發(fā)規(guī)則,可以限制進入容器的源IP地址:
iptables -I DOCKER-USER ! -s 10.108.11.178 -p tcp --dport 1521 -j DROP
其他記錄點:docker在啟動時是會在iptables上添加規(guī)則的,而firewalld服務啟動時,會將iptables上的規(guī)則全部清空,并把firewalld上的防火墻策略規(guī)則寫入到iptables中,此時docker因為防火墻規(guī)則被刪除就會不正常,需要重啟systemctl restart docker服務來重新刷寫防火墻規(guī)則到iptables上,所以我們在管理Docker端口時,應該使用iptables防火墻而不是firewalld防火墻服務。
參考地址:http://www.dbjr.com.cn/server/307655tdj.htm
又引發(fā)新的問題
按照第二種方案處理后,確實實現(xiàn)了iptables對docker容器的管理,實現(xiàn)了只允許特定IP訪問特定容器端口,但又引發(fā)新的問題,容器內部之間也無法通過防火墻,這個是我沒想到的,還要手動將容器的網段地址添加到DOCKER-USER鏈中去,才能保證容器內部相互通訊。
進入容器內部測試,發(fā)現(xiàn)網絡不通
添加docker容器的網段
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 4ac677e2fd2f bridge bridge local f28591fefa67 docker-project_default bridge local f32fea4be351 host host local dc907d235925 none null local [root@localhost ~]# [root@localhost ~]# docker inspect docker-project_default | grep Subnet "Subnet": "172.18.0.0/16", #所有docker使用docker-project_default bridge的網段 [root@localhost ~]#
放行容器網段訪問所有端口
[root@localhost ~]# iptables -I DOCKER-USER -p tcp -s 172.18.0.12/16 -j ACCEPT [root@localhost ~]# iptables -n -L DOCKER-USER Chain DOCKER-USER (1 references) target prot opt source destination ACCEPT tcp -- 172.18.0.0/16 0.0.0.0/0 #確保容器網絡規(guī)則在第一位 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5432 RETURN all -- 0.0.0.0/0 0.0.0.0/0
測試容器訪問其他容器端口,成功
[root@localhost ~]# docker exec -it tomcat bash root@2aedfa874301:/usr/local/tomcat# telnet postgres 5432 Trying 172.18.0.2... Connected to postgres. Escape character is '^]'.
三.Iptables基礎命令
關閉特定端口
iptables -A INPUT -p tcp --dport 1521 -j ACCEPT
允許特定IP訪問所有端口
iptables -I INPUT -s 10.108.11.178 -j ACCEPT
允許特定IP訪問特定端口
iptables -I DOCKER-USER ! -s 10.108.11.178 -p tcp --dport 1521 -j DROP
刪除規(guī)則
iptables -t filter -nL --line-number iptables -D INPUT 1
清空所有規(guī)則
iptables -F iptables -X iptables -Z
永久保存規(guī)則
#第一種方案 yum install iptables iptables-services -y systemctl start iptables.service && systemctl enable iptables.service service iptables save #第二種方案 保存 iptables-save > /etc/iptables/iptables.rules 恢復 iptables–restore < /etc/iptables/iptables.rules
到此這篇關于防火墻控制Docker端口開放與關閉的文章就介紹到這了,更多相關Docker端口開放關閉內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
docker安裝jenkins的過程并配置jdk、node和maven
本文介紹了如何從拉取Jenkins鏡像開始,通過創(chuàng)建文件夾、準備JDK、Maven和Node環(huán)境,修改settings.xml支持http協(xié)議,到建立Dockerfile進行Jenkins鏡像的二次打包,同時涉及容器的運行、Jenkins初始化設置、插件安裝和環(huán)境變量配置等步驟,幫助用戶成功部署并運行Jenkins服務2024-10-10Docker拉取鏡像失敗解決(connect: connection refused)
最近遇到Docker拉取centos鏡像時報錯,本文主要介紹了Docker拉取鏡像失敗解決(connect: connection refused),具有一定的參考價值,感興趣的可以了解一下2024-07-07