还在为Docker端口暴露而烦恼?还在为复杂的iptables和firewalld配置而头疼? 本文将带你深入浅出地了解Docker端口控制机制,并通过丰富的实战案例,教你如何利用iptables和firewalld精准控制Docker容器的端口访问权限。

docker iptables firewalld DOCKER-USER ufw 防火墙 不生效

在日常的部署过程中,为了规避扫描器对于我们服务器的探测,减轻漏洞修复的压力。或者想要防火墙对于中间件等敏感服务进行访问的保护,我们都有需求对于docker的端口进行访问控制。然而,在实际配置过程中,大家应该也发现了,在采用端口映射的方式进行端口放开的情况下,直接对于INPUT进行规则的配置,是不会生效的。而且,在网络上直接进行搜索,给出的答案往往就是对于INPUT进行规则的配置。

因此本文主要就是给出真正能够生效的方案,供大家参考:

首先对于这个问题,docker官方其实给出了解决方案,官方具体的文档为:https://docs.docker.com/network/iptables/

docker预留了一个自定义chain DOCKER-USER 用作规则的配置,下边给大家几个案例:

假如我们只希望开放本机的服务给192.168.1.1-192.168.1.3这3个IP进行访问,本机的业务网卡为eth0:
iptables -I DOCKER-USER -m iprange -i eth0 ! --src-range 192.168.1.1-192.168.1.3 -j DROP

假如我们只希望开放本机的3306端口给192.168.1.0/24这个网段进行访问,本机的业务网卡为eth0:
iptables -I DOCKER-USER -i eth0 -p tcp --dport 3306 ! -s 192.168.1.0/24 -j DROP

是不是很简单?
其余的一些配置参考:
iptables -I DOCKER-USER -i ens33 ! -s 192.168.1.201 -j DROP
iptables -I DOCKER-USER -m iprange -i ens33 ! --src-range 192.168.1.1-192.168.1.3 -j DROP
iptables -I DOCKER-USER -i ens33 ! -s 10.19.1.0/24 -j DROP

多个网段
iptables -I DOCKER-USER -i ens192 -p tcp  -j DROP
iptables -I DOCKER-USER -i ens192  -s 192.168.1.0/24 -j ACCEPT
iptables -I DOCKER-USER -i ens192  -s 192.168.1.0/24 -j ACCEPT

查看并删除规则,按照从上到下的顺序,比如删除此时的第1条规则
iptables -nvL
iptables -D DOCKER-USER 1 

注意!!!host模式启动的docker则需要对于INPUT链进行操作,比如:
iptables -I INPUT   -p tcp --dport 80 -j ACCEPT

20230713,补充一个坑

对于DOCKER-USER进行规则配置的时候,端口需要指定的使用原始docker的端口。
比如你启动docker时使用80 映射了原始的 8080
你在写规则的时候需要针对8080端口来写:
iptables -I DOCKER-USER -i ens192 -p tcp -m tcp --dport 8080 -j ACCEPT

当然,目前的linux发行版本普遍是没有默认安装iptables的,下边以centos7为例,对于iptables补包及服务配置做下说明:

centos7默认使用firewalld,因此假如使用iptables,请注意补包
systemctl stop firewalld
systemctl disable firewalld
yum -y install iptables-services
systemctl start iptables-service
systemctl enable iptables-service
开启服务器的防火墙服务后,需要重启一下docker服务,注入docker的默认规则
systemctl restart docker

注意,对于docker规则的持久化建议额外写一个脚本进行开机自启,不建议使用iptables-save对于规则进行持久化,容易影响到docker默认规则的注入,引发奇怪的问题。

本机二进制的端口正常透过INPUT进行控制即可。

同时,可能有些朋友并不希望重新安装iptables,直接透过firewalld进行配置行不行呢?答案是可以的,但是官方并不推荐,官方压根儿就没有给出firewalld的解决方案。此出是博主给出的方案,可以参考:

以上边3306的案例为例,
添加规则:
firewall-cmd  --direct --add-rule ipv4 filter DOCKER-USER 0 -i eth0 -p tcp --dport 3306 ! -s 192.168.1.0/24 -j DROP
重启防火墙并重启docker服务:
firewall-cmd --reload
systemctl restart docker
如需删除规则:
firewall-cmd  --direct --remove-rule ipv4 filter DOCKER-USER 0 -i eth0 -p tcp --dport 3306 ! -s 192.168.1.0/24 -j DROP

注意,不支持permanent参数,一加就会出现问题,比如下边这条:
firewall-cmd --permanent  --direct --add-rule ipv4 filter DOCKER-USER 0 -i eth0 -p tcp --dport 3306 ! -s 192.168.1.0/24 -j DROP

结论,不建议使用firewalld去进行存在docker的环境的管理,开启firewalld之后,除了ssh以及dhcp外,都要重新开启白名单。docker官方文档只提供iptables配置案例。

firewalld的基本操作补充:

firewall-cmd基础使用记录:
查看版本:firewall-cmd --version
查看帮助:firewall-cmd --help
显示状态:firewall-cmd --state
更新防火墙规则:firewall-cmd --reload
查看区域信息:firewall-cmd --get-active-zones

firewall-cmd  --list-all
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --reload
firewall-cmd --remove-port=80/tcp --permanent
firewall-cmd --reload
firewall-cmd --add-service=http
firewall-cmd --remove-service=http
富规则
firewall-cmd --add-rich-rule 'rule family="pv4" source address="192.168.0.102/32" port port="22" protocol="tp" accept' --permanent
firewall-cmd --add-rich-rule 'rule family="pv4" source address="0.0.0.0/0" pot port="80" protocol="tcp" accept' --permanent
删除:
firewall-cmd --remove-rich-rule 'rule family="pv4" source address="0.0.0.0/0" pot port="80" protocol="tcp" accept' --permanent

本来写到这边就可以结束了,但是博主对于DOCKER这条chain直接加规则也做了验证,结论是可以的,也可以生效。这个只是补充其他方案的认识,大家看下就可以了,实践中参考最上边的DOCKER-USER chain即可。

1.1设置黑名单
全局
iptables -I DOCKER -i ens33 -p tcp  -j DROP
某个端口
iptables -I DOCKER -i ens33 -p tcp --dport 80 -j DROP
某个容器的端口
iptables -I DOCKER -i ens33 -p tcp -d 172.17.0.3 --dport 80 -j DROP

1.2放通白名单
某个端口
iptables -I DOCKER -i ens33  -s 192.168.100.201 -p tcp --dport 80 -j ACCEPT
某个容器服务的端口
iptables -I DOCKER -i ens33  -s 192.168.100.201 -p tcp -d 172.17.0.3 --dport 80 -j ACCEPT

其他:
#多个端口的写法,最多15个端口
iptables -I DOCKER -i ens33 -p tcp -m multiport --dports 80,443 -j DROP
#删除无效的规则
iptables [-t table] -D chain rulenum
iptables -D DOCKER 1
#查看DOCKER chain的规则
iptables -vnL
iptables -vnL DOCKER

谢谢观看,本文预计会补充视频教程,届时再将视频进行补充。