公网Docker的端口暴露风险
2025-01-02 18:46:13 34
场景
默认配置下docker启动的容器, 如果进行了端口映射
docker run --network bgnet --ip 172.18.0.3 --name http03 -p 9090:8080 http-docker则docker会修改iptables的规则, 以支持对应端口的流量转发.
如果机器使用firewalld关闭入方向的端口, 但由于docker添加的规则优先级最高, 此时会导致firewalld配置的策略失效.
以上面的命令为例, 即使firewalld屏蔽了所有端口, 外部也能通过9090访问到服务. 这样暴露是较危险的
github的讨论: https://github.com/moby/moby/issues/22054
解决方法
1. 修改docker启动参数
在docker启动时添加–iptables=false参数来禁止docker对iptables的操作
2. nginx转发
docker run --network rootnet --ip 172.18.0.4 --name http04 -p 127.0.0.1:9091:8080 http-docker-p 127.0.0.1:19091:8080 将容器的8080端口只发布到127.0.0.1的19091
nginx监听9091, 再通过nginx转发到这个19091端口, 这样firewall就能通过控制nginx的9091端口, 间接决定这个容器是否对外网提供服务
3. 定义iptables规则限制
docker run --network rootnet --ip 172.18.0.3 --name http03 -p 9090:8080 -d http-docker这个容器将端口9090发布到0.0.0.0上
3.1 修改iptables DOCKER链规则
# 删除docker为容器添加的默认规则(允许任意流量访问172.18.0.3:8080)
iptables -D DOCKER 1
# 仅允许源ip为192.168.143.1的流量访问服务
iptables -I DOCKER -s 192.168.143.1 -d 172.18.0.3 -p tcp --dport 8080 -j ACCEPTsystemctl restart dockerdocker重启后, 手动设置的规则消失. 仍然是任意端口都能访问服务
3.1.1 iptables规则持久化
参照https://blog.csdn.net/qq_43665434/article/details/127069813用iptables-services保存规则, 将#3.1设置的规则持久化
dnf install iptables-services -y
service iptables save
systemctl restart iptables3.1.2 重启docker后, 规则变为默认, 手动设置的也被清空. 需要手动重启iptables使设置的规则生效
systemctl restart docker
systemctl restart iptables3.1.3 重启http03服务, 手动设置的未被清空, 但docker重新添加了默认规则. 需要手动重启iptables使设置的规则生效
docker restart http03
systemctl restart iptables3.2 修改iptables DOCKER-USER链规则
iptables -D DOCKER-USER 1
# 禁止所有流量访问8080
iptables -I DOCKER-USER -p tcp --dport 8080 -j DROP
# 仅允许192.168.143.1访问
iptables -I DOCKER-USER -s 192.168.143.1 -p tcp --dport 8080 -j ACCEPT3.2.1 重启docker和http03容器, DOCKER-USER规则仍然在
systemctl restart docker
docker start http03 http043.2.2 重启机器, DOCKER-USER规则消失
rebootservice iptables save保存规则后, 需要手动重启iptables, 保存的规则才能重新加载
systemctl restart iptables3.2.2.1 配置开机自动加载iptables规则
开机自动配置iptables规则
vim /etc/systemd/system/custom-iptables.serviceservice iptables save是默认保存到/etc/sysconfig/iptables的
docker启动后再运行, 仅运行一次
[Unit]
Description=Run custom commands after docker
After=docker.service
[Service]
Type=oneshot
ExecStart=/bin/bash -c "iptables -D DOCKER-USER 1 && /usr/sbin/iptables-restore < /etc/sysconfig/iptables"
[Install]
WantedBy=multi-user.target重载配置
systemctl daemon-reload配置开机启动
systemctl enable custom-iptables.service重启后规则未消失, 端口正常限制
总结
| 方案 | 优点 | 问题 |
| 修改docker启动参数 | 1. 可以通过firewall进行统一管理 2. 启动新容器, 外网流量默认无法访问 | 容器间无法进行内部通信 |
| nginx转发 | 1. 可以通过firewall进行统一管理 2. 启动新容器, 外网流量默认无法访问 | 1. 已经创建的容器不方便修改 2. 需要多配置一个组件, 增加运维成本 |
| iptables DOCKER | 能管理到正在运行的容器 | 1. 增加运维成本, 重启机器或docker后, 必须手动重启iptables 2. 不能通过firewall进行统一管理 |
| iptables DOCKER-UESR | 1. 能管理到正在运行的容器 2. 重启docker规则不会消失 | 1. 增加运维成本 2. 不能通过firewall进行统一管理 |






