背景

文章参考前提,系统中已正确安装 ufw 防火墙以及 docker

linux 中 docker 默认会自行配置 iptables 进行流量转发,从而绕过 ufw 规则, 造成 ufw 无法监管 docker 流量的问题

通过本文方式可解决 dockerufw 的适配问题,从而使 ufw 可以正常控制 docker 的流量

docker 配置修改

编辑docker配置文件

sudo vim /etc/docker/daemon.json

添加如下配置到配置文件中

{
	"iptables": false
}

iptables 参数作用:关闭docker的自动iptables转发

系统配置修改

开启内核ipv4的转发

临时生效

sudo sysctl -w net.ipv4.ip_forward=1

永久生效

将以下内容追加到 /etc/sysctl.conf

net.ipv4.ip_forward=1

追加完成后执行 sudo sysctl -p 生效

检查配置是否生效

cat /proc/sys/net/ipv4/ip_forward

输出是:

  • 1 表示已开启 ✅

  • 0 表示未开启 ❌

UFW 配置修改

修改 UFW 的默认转发策略

编辑 /etc/default/ufw

sudo vim /etc/default/ufw

找到 DEFAULT_FORWARD_POLICY 配置,将其值修改为 ACCEPT

DEFAULT_FORWARD_POLICY="ACCEPT"

添加 NAT 规则到 UFW

编辑 /etc/ufw/before.rules,在开头(*filter 之前)添加:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 172.17.0.0/16 -o etho -j MASQUERADE
COMMIT

-A POSTROUTING -s 172.17.0.0/16 -o etho -j MASQUERADE 解释:

  1. -A POSTROUTING

    • -Aiptables 的一个参数,表示向指定链(POSTROUTING)添加一条规则。

    • POSTROUTINGiptables 的一个链,表示数据包经过所有路由和 NAT 处理后,准备离开网络接口时的处理。简单来说,这个链处理的是出网流量。

  2. -s 172.17.0.0/16

    • -s 指定了源 IP 地址或地址段

    • 172.17.0.0/16 表示 Docker 默认的桥接网络子网,这通常是 Docker 默认配置的 bridge 网络的子网地址。这个地址段包含了所有 Docker 容器的 IP 地址,例如 172.17.0.2172.17.0.3 等。

  3. -o etho

    • -o 表示出接口(Outbound Interface)。

    • eth0 是宿主机的网络接口,通常用于连接到外部网络(例如互联网)。在这条规则中,eth0 是容器访问外部网络时数据包将通过的接口。

  4. -j MASQUERADE

    • -j 用于指定跳转到的目标,MASQUERADE 表示伪装(NAT)。

    • MASQUERADE 会将数据包的源 IP 地址替换为出接口(即 eth0)的 IP 地址。这是为了让外部网络看到宿主机的 IP 地址,而不是容器的内部 IP 地址。

总结:

  1. 这条 NAT 规则不增加,docker 容器将无法连接互联网!!!

  2. -s xxx.xxx.xxx.xxx 中的IP地址通过 docker network inspect {docker 网络ID} 命令进行查询, 然后将结果部分的ip对应修改到此

  3. -o 网卡名称 中的 网卡名称 通过 ifconfig 或者 ip addr 进行查询,将宿主机中用来连接互联网的网卡名称填入到此即可

  4. 如果docker有多个network需要填写多条到此,示例如下:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 172.17.0.0/16 -o etho -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 -o etho -j MASQUERADE
-A POSTROUTING -s 172.19.0.0/16 -o etho -j MASQUERADE
...
COMMIT

重启UFW防火墙

sudo ufw disable
sudo ufw enable