[运维篇]屏蔽Docker映射端口外部访问

某天排查服务器时,我意外发现自己用Docker部署的几个服务竟然能够被外部直接访问,而并没有被主机防火墙(UFW)拦截。换句话说,这些本应只在内网使用的服务,居然在公网“裸奔”了好几个月。

查阅资料后才知道,Docker的端口映射与防火墙的工作方式类似,它们都会通过修改 iptables 来控制流量。但关键在于:Docker会自动插入自己的iptables规则,而且这些规则的位置通常排在防火墙规则之前。结果就是——流量在到达UFW的过滤链之前,就已经被Docker自己的规则放行了。

因此,即使在UFW中明确设置了deny,也很可能无法真正阻挡通过Docker映射端口进入的访问。那么应该如何配置iptables规则来处理这个问题呢?

(当然很多云服务商在主机防火墙外,还有一系列的安全组规则,可以起到端口不对外暴露的效果)

两行命令解决这个问题

所有进入容器的流量,在iptables匹配Docker自己的规则之前,都会先经过DOCKER-USER这一规则链,因此我们可以将它作为一个流量控制点。

先使用ip addr查看默认的外网网卡名称,和Docker使用的默认内网IP网段(这里不使用Docker虚拟网卡名称的原因是,可能会有多个网卡需要添加屏蔽,使用IP网段会更加容易)。

以外网网卡名称为enp1s0,Docker使用的内网IP网段为172.16.0.0/12为例。

顺序很重要,添加如下的两条iptables规则即可生效:

  1. 先放行容器出网连接的回包(避免容器无法访问外网)
  2. 再丢弃外网到容器网段的新建连接(阻止公网访问Docker映射到宿主机端口)
    sudo iptables -I DOCKER-USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    sudo iptables -I DOCKER-USER 2 -i enp1s0 -d 172.16.0.0/12 -m conntrack --ctstate NEW -j DROP

避免规则重启后消失

由于iptables规则重启后会消失,因此还需要使用iptables-persistent插件对规则进行持久化保存

安装iptables-persistent插件

sudo apt install iptables-persistent

使用命令持久化规则:

sudo iptables-save | sudo tee /etc/iptables/rules.v4 > /dev/null

不再需要这些规则了

当不需要继续拦截外网直接访问Docker容器映射的端口时,可以通过如下的方法删除规则:

先查询为DOCKER-USER链创建的规则并列出规则行号

sudo iptables -L DOCKER-USER -n --line-numbers

然后根据行号删除规则,这里以删除1、2行规则为例

sudo iptables -D DOCKER-USER 1
sudo iptables -D DOCKER-USER 2

发布者

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注