目前我们的系统部署在客户专网环境,由于业务特殊性,安全等级非常高,对于专网的主机客户要求我们启用防火墙并配置安全访问策略。业务系统使用的基础组件有Mysql、redis、mongodb等数据库,且都是使用docker来部署的,现在需要使用firewalld防火墙服务对容器配置安全策略。
环境信息如下:
需求如下:192.168.1.48这台使用docker部署了mysql、redis、mongodb服务,另外有三台主机分别是192.168.1.11、192.168.1.12、192.168.1.13分别部署了平台系统的java应用,现在需要对192.168.1.48上部署的mysql、redis、mongodb配置ip访问白名单,即只允许192.168.1.11、192.168.1.12、192.168.1.13这三台主机能够访问mysql、redis、mongodb这三个服务。
如下图所示:
为了保护Docker暴露的端口不受外部访问的影响,可以使用firewalld配置防火墙规则,只允许特定的IP访问。 通过让firewalld创建DOCKER-USER链,我们可以实现由 firewalld维护的安全Docker端口, Docker处理iptables规则以提供网络隔离。
本文基于一下环境,如下图所示:
[root@host-48 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@host-48 ~]# firewall-cmd -V
0.5.3
[root@host-48 ~]# docker --version
Docker version 20.10.9, build c2ea9bc
1、设置SELINUX权限
setenforce 0
sed -i 's/^SELINUX=.*$/SELINUX=disabled/g' /etc/sysconfig/selinux
sed -i 's/^SELINUX=.*$/SELINUX=disabled/g' /etc/selinux/config
2、查看docker自定义默认子网(下面操作需用到)
[root@host-48 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a141b02eee12 bridge bridge local
67edabe08e5e default_bridge bridge local
fd32ddb492d0 host host local
eccff239aa09 none null local
[root@host-48 ~]# docker network inspect 67edabe08e5e | grep Subnet
"Subnet": "172.29.96.0/20",
说明:提示: 172.29.96.0/20是我当前环境自定义的Docker的子网地址, 你也可以改为你实际的Docker子网地址
3、查看自定义默认网桥名称(下面操作需用到)
4、清除所有iptables配置并重启Docker
[root@host-48 ~]# iptables -t filter -F
[root@host-48 ~]# iptables -t filter -X
[root@host-48 ~]# iptables -t nat -F
[root@host-48 ~]# iptables -t nat -X
[root@host-48 ~]# systemctl restart docker
1、停止Docker服务
[root@host-48 ~]# systemctl stop docker
2、启动firewalld服务
[root@host-48 ~]# systemctl start firewalld
3、在firewalld中重建DOCKER-USER iptables chain(请忽略任何警告)
[root@host-48 ~]# firewall-cmd --permanent --direct --remove-chain ipv4 filter DOCKER-USER
Warning: NOT_ENABLED: chain 'DOCKER-USER' is not in 'ipv4:filter'
success
[root@host-48 ~]# firewall-cmd --permanent --direct --remove-rules ipv4 filter DOCKER-USER
success
[root@host-48 ~]# firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER
success
4、添加iptables规则到DOCKER-USER chain
#允许容器与外部网络连接
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-m conntrack \
--ctstate RELATED,ESTABLISHED -j ACCEPT \
-m comment --comment 'Allow containers to connect to the outside world'
#允许内部容器通信
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-j RETURN \
-s 172.29.96.0/20 \
-m comment --comment 'allow internal docker communication'
说明:172.29.96.0/20为docker服务默认子网,可参考上面命令
5、为机器192.168.1.11、192.168.1.12、192.168.1.13配置允许访问 Mysql Docker 3306端口、mongodb Docker 17017端口、redis Docker 6379端口,优先级为1(您可以在以后添加更多优先级为0的规则。
注意:这里的端口是指的Docker的内部端口3306、27017、6379,而不是映射的外部端口53000、17000、47000
#配置192.168.1.11主机访问容器的3306、27017、6379端口
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-o br-716a787bc54d \
-p tcp -m multiport \
--dports 3306,27017,6379 -s 192.168.1.11 -j ACCEPT \
-m comment \
--comment 'Allow IP 192.168.1.11 to access http and https docker ports'
#配置192.168.1.12主机访问容器的3306、27017、6379端口
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-o br-716a787bc54d \
-p tcp -m multiport \
--dports 3306,27017,6379 -s 192.168.1.12 -j ACCEPT \
-m comment \
--comment 'Allow IP 192.168.1.12 to access http and https docker ports'
#配置192.168.1.13主机访问容器的3306、27017、6379端口
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 \
-o br-716a787bc54d \
-p tcp -m multiport \
--dports 3306,27017,6379 -s 192.168.1.13 -j ACCEPT \
-m comment \
--comment 'Allow IP 192.168.1.13 to access http and https docker ports'
说明:br-716a787bc54d为docker默认网桥的名称,可参考上面命令
注意:这里的ip地址192.168.1.11、192.168.1.12、192.168.1.13不能写成192.168.1.11/24、192.168.1.12/24、192.168.1.13/24,否则规则文件source ip会变成192.168.1.0/24,具体原因不清楚。如果规则文件source ip变成了192.168.1.0/24,那么防火墙的意义就没有达到预期的效果,这也是不能容忍的,所以这里大家需要注意。如下图所示:
6、阻止所有其他IP,此规则的优先级最低,您可以稍后在此规则之前添加规则
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 10 \
-j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'
注意:这里必须设置REJECT,否则上面设置的规则没有太大意义,会导致其他的主机也可以访问。
7、激活规则
[root@host-48 ~]# firewall-cmd --reload
8、启动Docker
[root@host-48 ~]# systemctl start docker
9、配置完成后查看规则
方法一:firewall-cmd --direct --get-all-rules
方法二:cat /etc/firewalld/direct.xml
方法三:iptables -L DOCKER-USER -n
10、对设定的防火墙规则进行测试
方法一:将日志记录添加到具有最高优先级的DOCKER-USER链中
[root@host-48 firewalld]# firewall-cmd --direct --add-rule ipv4 filter DOCKER-USER 0 -j LOG --log-prefix ' DOCKER TCP: '
来自192.168.1.11的访问被允许,如下图所示:
来自192.168.1.8的访问被拒绝,如下图所示:
方法二:探测端口的方式
来自192.168.1.11的访问被允许,如下图所示:
来自192.168.1.8的访问被拒绝,如下图所示:
11、重置firewalld,必须先关闭docker
[root@host-48 ~]# systemctl stop docker
[root@host-48 ~]# systemctl stop firewalld
[root@host-48 ~]# rm -f /etc/firewalld/direct.xml
[root@host-48 ~]# rm -f /etc/firewalld/zones/docker.xml
[root@host-48 ~]# systemctl start docker
[root@host-48 ~]# systemctl start firewalld
更多详细内容请参考:Linux运维实战总结