《Linux运维总结:基于Centos系统使用firewalld为docker容器配置防火墙策略》

一、背景

目前我们的系统部署在客户专网环境,由于业务特殊性,安全等级非常高,对于专网的主机客户要求我们启用防火墙并配置安全访问策略。业务系统使用的基础组件有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

2.1、准备工作

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

2.2、配置firewalld

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
《Linux运维总结:基于Centos系统使用firewalld为docker容器配置防火墙策略》_第1张图片
方法三: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的访问被允许,如下图所示:
《Linux运维总结:基于Centos系统使用firewalld为docker容器配置防火墙策略》_第2张图片
来自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运维实战总结

你可能感兴趣的:(《Linux运维实战总结》,docker,linux,运维)