公网Docker的端口暴露风险
2025-01-02 18:46:13 4
场景
默认配置下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 ACCEPT
systemctl restart docker
docker重启后, 手动设置的规则消失. 仍然是任意端口都能访问服务
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 iptables
3.1.2 重启docker后, 规则变为默认, 手动设置的也被清空. 需要手动重启iptables使设置的规则生效
systemctl restart docker
systemctl restart iptables
3.1.3 重启http03服务, 手动设置的未被清空, 但docker重新添加了默认规则. 需要手动重启iptables使设置的规则生效
docker restart http03
systemctl restart iptables
3.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 ACCEPT
3.2.1 重启docker和http03容器, DOCKER-USER规则仍然在
systemctl restart docker
docker start http03 http04
3.2.2 重启机器, DOCKER-USER规则消失
reboot
service iptables save保存规则后, 需要手动重启iptables, 保存的规则才能重新加载
systemctl restart iptables
3.2.2.1 配置开机自动加载iptables规则
开机自动配置iptables规则
vim /etc/systemd/system/custom-iptables.service
service 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进行统一管理 |