Docker 容器网络配置,防止被内网攻击
为什么容器需要防内网攻击
默认情况下,Docker 使用 bridge 网络模式,宿主机和同网段设备都能访问容器暴露的端口。
如果内网存在不安全设备,攻击者可能直接扫描并入侵未加固的容器。通过合理配置容器网络,可以做到端口隔离、访问来源限制,从根本上降低风险。
准备工作
- 已安装 Docker(版本 20.10+),操作均通过 SSH 或服务器终端执行。
- 确保你有 root 或 sudo 权限。
- 了解需要运行的容器及其对外服务端口(例如 Nginx 的 80、MySQL 的 3306)。
如果使用宝塔面板,可以在 软件商店 → Docker 管理器 中查看已安装的容器和网络设置,但本文以命令行操作为主,更灵活通用。
第一步:使用自定义网络代替默认 bridge
Docker 的默认 bridge 网络允许所有容器互通,也允许宿主机所有接口访问。
创建一个自定义网络可以更细粒度控制:
# 创建一个隔离网络,并禁止容器内 DNS 解析外网(可选)
docker network create \
--driver bridge \
--opt com.docker.network.bridge.name=isolated_bridge \
--subnet=172.20.0.0/16 \
--gateway=172.20.0.1 \
isolated_net
这条命令创建了一个名为 isolated_net 的桥接网络,子网为 172.20.0.0/16。
再运行容器时指定该网络:
docker run -d \
--name my_web \
--network isolated_net \
-p 127.0.0.1:8080:80 \
nginx:alpine
关键点:-p 127.0.0.1:8080:80 表示端口只监听在本地回环地址,外部网络(包括内网其他设备)无法直接访问容器 80 端口,必须通过宿主机本机才能访问。
如果你希望特定内网 IP 才能访问,见第二步。
第二步:借助 iptables 限制来源 IP
如果需要让内网某台机器(例如 192.168.1.100)访问容器,而其他设备无法访问,可以在宿主机上添加 iptables 规则:
# 允许特定 IP 访问宿主机的 8080 端口(即映射后的容器端口)
iptables -A DOCKER-USER -i eth0 -p tcp --dport 8080 -s 192.168.1.100 -j ACCEPT
# 拒绝其他所有来源
iptables -A DOCKER-USER -i eth0 -p tcp --dport 8080 -j DROP
注意:DOCKER-USER 链是 Docker 预留的自定义规则插入点,重启 Docker 或容器后不会被清理。
检查生效:
iptables -L DOCKER-USER -v -n
如果使用宝塔面板,可以在 安全 → 系统防火墙 中添加端口放行规则时选择“指定 IP”来源,但不能像 iptables 命令那样灵活。
宝塔的防火墙规则与 iptables 并行,建议优先用命令行。
第三步:清理不必要的端口暴露
检查当前所有运行容器暴露的端口:
docker ps --format "table {{.Names}} {{.Ports}}"
如果某个容器只需要在容器间内部通信(例如应用服务与 Redis),不要使用 -p 映射端口,直接加入自定义网络即可通过容器名访问。
示例:
docker run -d --name my_redis --network isolated_net redis:alpine
# 应用容器通过主机名 my_redis 连接
同时,检查宿主机上是否有防火墙规则未限制容器端口。
建议默认禁止所有入站映射:
iptables -P DOCKER-USER DROP
但要注意:这条命令会将所有 Docker 相关的外部入站连接默认丢弃,可能会影响合法流量。
建议先在测试环境验证,然后只针对特定端口放行。
避坑指南
- 不要直接修改默认的 bridge 网络:默认 bridge 的 iptables 规则重启 Docker 后可能被重置,自定义网络更稳定。
- 端口绑定 0.0.0.0 风险:
-p 80:80等于外界所有 IP 都可访问,务必改为-p 127.0.0.1:80:80或-p 特定内网IP:80:80。 - iptables 规则重启后失效?:如果宿主机重启且 iptables 未持久化,规则会丢失。建议使用
iptables-save > /etc/iptables/rules.v4(Debian/Ubuntu)或安装iptables-persistent。
常见问题
Q:配置后容器之间不能通信了怎么办?
A:确保它们加入同一个自定义网络,例如 isolated_net。不同自定义网络之间默认隔离。
Q:使用宝塔面板能不能实现 IP 白名单?
A:可以,在宝塔安全管理的系统防火墙中添加端口放行时,选择“指定 IP”,填入允许的 IP 即可。但注意宝塔的规则会独立操作,优先于 Docker 的过滤。如果宝塔规则放行了所有来源(0.0.0.0/0),则即使 iptables 有限制也无法阻断。建议两者配合,保持一致。
Q:如何验证配置是否生效?
A:从内网另一台机器用 telnet 宿主机IP 8080 测试,白名单之外的 IP 应该 telnet 失败(连接超时或被拒)。
效果验证指南
- 在宿主机本地执行
curl 127.0.0.1:8080,应能正常返回容器响应。 - 从内网其他机器(非白名单 IP)执行
curl http://宿主机IP:8080,应无响应或提示拒绝连接。 - 运行
iptables -L DOCKER-USER -v -n查看规则匹配次数,确认有流量被 DROP。
如果你正在处理 Docker 容器网络配置,防止被内网攻击,建议先按本文步骤完整执行,再根据自己的环境做微调;
遇到异常时优先回看避坑和高频问题部分。