在实际使用野草云服务器部署 Docker 服务过程中,我发现了一个非常容易被忽视但极具风险的安全问题------野草云的防火墙逻辑与 Docker 默认行为之间存在冲突,如果配置不当,可能会导致容器服务被意外暴露在公网,甚至绕过你设置的"拒绝访问"规则。
这篇文章将分享我真实的排查过程、技术原理分析,以及如何正确防止 Docker 容器被穿透防火墙暴露在公网。
一、现象描述
-
我在 Docker 启动容器时设置了如下端口映射:
docker run -p 127.0.0.1:9080:80 my-web
按照常理,只有本地能访问 9080,外部是不能访问的。
-
然而即使我没有在野草云的防火墙面板放通 9080 端口 ,外部依然可以直接访问
http://服务器IP:9080/
。 -
更令人不安的是:即使我在野草云面板中明确设置了"拒绝 9080 TCP 访问",服务仍然能被公网访问。
二、初步排查
1. 检查 iptables
:未发现放通规则
sudo iptables -L -n -v
未发现有 ACCEPT 针对 9080 的规则。
2. 查看 Docker NAT 表
sudo iptables -t nat -L -n -v
发现存在如下规则:
DNAT tcp -- 0.0.0.0/0 tcp dpt:9080 to:172.17.0.2:80
说明 Docker 自动插入了端口转发规则。
3. 使用 ss
命令确认监听状态:
ss -tuln | grep 9080
显示监听 0.0.0.0:9080
,说明 Docker 绑定在所有网卡。
三、确认野草云防火墙是"系统级"防火墙
我进一步测试了 Docker 配置中的 iptables
开关:
在 /etc/docker/daemon.json
中加入:
{
"iptables": false
}
重启 Docker 之后,Docker 不再添加 iptables 转发规则,此时访问 IP:9080
失败,防火墙封锁生效。
然后我在宝塔面板的防火墙中手动放通 9080 ,再次访问 IP:9080
,可以访问成功。
✅ 结论:野草云的防火墙实际与宝塔防火墙处于同级,控制的是系统内的 iptables(而非网络层防火墙)。
这就意味着,野草云所谓"防火墙拒绝某端口"其实只是帮你设置了宿主机 iptables 规则,并不能真正隔离容器被 Docker 映射暴露的端口。
四、Docker 被绕防火墙的根本原因
-
Docker 使用 NAT 表(不是 filter 表)插入转发规则,将外部端口直接映射到容器内部。
-
这些规则默认优先于 ufw、firewalld、野草云面板控制的规则。
-
如果不设置额外规则,容器端口会直接暴露在公网,而你在防火墙中以为已经"封掉了"。
五、安全建议与防护措施
禁用 Docker 改写防火墙:
在/etc/docker/daemon.json里添加
{
"iptables": false
}
注意:这样做后所有网络规则需你手动维护。因为我使用的是宝塔面板,在测试里发现,所谓野草云防火墙其实和宝塔防火墙是同级的(或者说是同个东西),意思就是在「宝塔面板-安全」放通和拒绝与在「野草云服务器管理页面-防火墙」放通和拒绝效果是一致的(第三点)。所以你配置了iptables为false之后,使用docker要开关端口直接使用宝塔就行了。
六、总结
野草云虽然提供了"防火墙"功能,但其实质是控制服务器内部的 iptables,并非真正意义上的网络层防火墙。这种设计在 Docker 的 NAT 行为下容易被绕过,造成服务意外暴露。
建议使用野草云的开发者:
-
明确野草云面板防火墙是系统级的
-
使用docker最好设置daemon.json中的iptables为false
-
使用宝塔或者手动管理iptables