9.2 KiB
MinIO 9000/9001 端口局域网无法访问问题排查报告
日期:2026-07-12 服务器 IP:10.68.223.254 涉及服务:MinIO(Docker 容器,1Panel 管理) 状态:未完全复现,已恢复原样
1. 问题描述
用户反馈:MinIO 容器的 9000(API)和 9001(控制台)端口已在防火墙开放,但局域网无法访问。从另一台机器扫描 10.68.223.254 的 1-10000 端口,只发现 22、5230、6060 端口开放,9000 和 9001 端口显示为关闭。
2. 排查过程
2.1 检查防火墙规则
public zone ports:
10086/tcp 22/tcp 9000/tcp 8100/tcp 18686/tcp 3306/tcp 8088/tcp 3307/tcp 5230/tcp 8080/tcp 5180/tcp 6060/tcp 5901/tcp
- 9000 端口在 public zone 的 ports 列表中 ✓
- 9001 端口不在 ports 列表中,只有一条 rich rule 限制
11.1.1.0/24网段可访问
发现:9001 端口只对 11.1.1.0/24 网段开放,其他网段无法访问。但 9000 端口已全局开放,不应该有问题。
2.2 检查 MinIO 配置
发现 MinIO 容器有两个关键环境变量绑定到 127.0.0.1:
MINIO_SERVER_URL=http://127.0.0.1:9000
MINIO_BROWSER_REDIRECT_URL=http://127.0.0.1:9001
推测:这两个变量可能导致 MinIO 在处理请求时重定向到 127.0.0.1,使局域网客户端无法访问。
2.3 检查 Docker 端口映射
docker-proxy 在监听 0.0.0.0:9000 和 0.0.0.0:9001
nat 表有 DNAT 规则:tcp dpt:9000 to:172.20.0.3:9000
Docker 端口映射正常,docker-proxy 也在监听。
2.4 检查 iptables FORWARD 链
发现 FORWARD 链末尾有 firewalld 的 REJECT 规则:
23 REJECT 0 -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
推测:Docker 端口映射的流量走 FORWARD 链,被末尾的 REJECT 规则拦截。虽然 firewalld 在 public zone 开放了 9000 端口,但那是 INPUT 链的规则,对 FORWARD 链无效。
2.5 尝试修复(操作过程中出现意外)
在尝试通过 firewall-cmd --direct --add-rule 向 FORWARD 链添加放行规则时:
- 多次执行
--direct --add-rule失败,报错iptables-restore: line 2 failed - 直接编辑
/etc/firewalld/direct.xml文件,导致规则不一致 - 执行
firewall-cmd --reload后,/etc/firewalld/zones/public.xml被覆盖为只剩<masquerade/>,所有端口和规则丢失 - 22 端口被锁,SSH 无法连接(用户通过 RustDesk 远程桌面仍可操作)
2.6 恢复防火墙配置
- 从
/etc/firewalld/zones/public.xml.old恢复了完整的端口列表和服务 - 在恢复的 public.xml 中添加了
<masquerade/> - 清空了 direct.xml(删除了之前添加的 FORWARD 规则)
- 重启 firewalld,所有端口恢复正常
2.7 修改 MinIO 配置
从 docker-compose.yml 中删除了以下两行:
MINIO_BROWSER_REDIRECT_URL: http://127.0.0.1:9001
MINIO_SERVER_URL: http://127.0.0.1:9000
重启 MinIO 容器后,局域网可以访问 9000 和 9001 端口。
3. 复现尝试
用户反馈:之前 MinIO 配置从未改动过,一直可以正常访问。要求复现问题。
3.1 尝试一:firewall-cmd --reload
假设:firewalld reload 会清空 Docker 的 iptables 规则,导致流量无法通过 FORWARD 链。
操作:
- 删除手动添加的 FORWARD_direct 规则
- 执行
firewall-cmd --reload
结果:9000 端口仍然可以访问。Docker 的 nat 表 DNAT 规则和 filter 表 FORWARD/DOCKER 链规则在 reload 后没有被清掉。
3.2 尝试二:停 Docker → reload firewalld → 启 Docker
假设:Docker 和 firewalld 的启动顺序会影响 iptables 规则的排列位置。
操作:
sudo systemctl stop dockersudo firewall-cmd --reloadsudo systemctl start docker
结果:Docker 重启后,自动用 iptables -I(insert)将规则插入到 FORWARD 链最顶部,在 firewalld 的 REJECT 规则之前。9000 端口仍然可以访问。
3.3 尝试三:还原 MinIO 配置,只 reload firewalld
假设:问题是 MinIO 的 MINIO_SERVER_URL=http://127.0.0.1:9000 导致的。
操作:
- 还原 docker-compose.yml 中的
MINIO_SERVER_URL和MINIO_BROWSER_REDIRECT_URL - 重启 MinIO 容器
- 不动防火墙,直接测试
结果:9000 和 9001 端口都可以正常访问。问题没有复现。
4. 猜想与分析
猜想一:MinIO 配置导致
MINIO_SERVER_URL=http://127.0.0.1:9000 会导致 MinIO 控制台在登录后重定向到 http://127.0.0.1:9001,局域网客户端浏览器会尝试访问自己的 9001 端口,导致访问失败。
问题:这只能解释浏览器访问控制台失败,不能解释端口扫描工具显示 9000 端口关闭。而且还原配置后也能正常访问,无法复现。
猜想二:firewalld reload 清空了 Docker 规则
firewall-cmd --reload 会重建 iptables 规则,可能清空 Docker 插入的 FORWARD 和 nat 规则。
问题:实际测试发现 firewall-cmd --reload 并不会清空 Docker 的规则。Docker 的规则在 reload 后依然存在。
猜想三:Docker 启动时 iptables 操作失败
Docker 启动容器时需要操作 iptables 添加 DNAT 和 FORWARD 规则。如果当时 iptables 处于异常状态(比如 firewalld 正在重建规则),Docker 的 iptables 操作可能失败,导致规则没有正确添加。
佐证:排查过程中曾尝试 docker restart minio,报错:
Cannot restart container minio: driver failed programming external connectivity
iptables failed: iptables --wait -t nat -A DOCKER -p tcp --dport 9001 -j DNAT ...
iptables: No chain/target/match by that name.
这说明 nat 表的 DOCKER 链被删了,Docker 无法添加 DNAT 规则。
猜想四:操作导致的临时状态
排查过程中多次执行 firewall-cmd --direct --add-rule,每次都报错 iptables-restore: line 2 failed。这些失败的操作可能导致 iptables 处于不一致的状态,使 Docker 的规则部分丢失或位置异常。
佐证:用户最初反馈问题时,可能是在某次 firewalld 操作后出现的。而我开始排查时,由于又执行了多次 firewalld 操作,可能加剧了规则的不一致。
猜想五:Docker 和 firewalld 的启动顺序竞争
如果 firewalld 和 Docker 同时启动,可能出现竞争条件:
- Docker 先启动,添加了 iptables 规则
- firewalld 后启动,重建 iptables 规则,清掉了 Docker 的规则
- Docker 没有感知到规则被清掉,不会自动恢复
问题:这个猜想很难复现,因为需要精确控制两个服务的启动时序。
5. 未查明的原因
综合以上分析,真正的原因未能确定。可能的原因包括:
- Docker 和 firewalld 的启动顺序竞争:某次系统重启后,firewalld 在 Docker 之后启动,清掉了 Docker 的 iptables 规则,而 Docker 没有自动恢复
- iptables 异常状态:某次 firewalld 操作(如 reload 或 direct 规则添加失败)导致 iptables 处于不一致状态,Docker 的规则部分丢失
- MinIO 配置叠加效应:
MINIO_SERVER_URL=http://127.0.0.1:9000在某些情况下可能导致 MinIO 拒绝非本地请求,使端口扫描工具误判端口关闭 - 临时网络问题:可能是当时的临时网络或路由问题,后续自然恢复
6. 最终状态
防火墙
- public zone:所有端口已恢复(22、9000、9001、8080、5180、6060、5901 等)
- 服务:ssh、mdns、dhcpv6-client
- masquerade:已开启
- rich rules:11.1.1.0/24 的 137-139、445、9001 规则已恢复
- direct.xml:已清空(不需要额外的 FORWARD 规则)
MinIO
- 配置已还原为原始状态(
MINIO_SERVER_URL=http://127.0.0.1:9000) - 容器正常运行
- 9000 和 9001 端口可从局域网正常访问
Docker
- iptables 规则正常
- nat 表 DOCKER 链有 DNAT 规则
- filter 表 FORWARD 链有 Docker 的 ACCEPT 规则在顶部
- filter 表 DOCKER 链有 9000/9001 的 ACCEPT 规则
7. 经验教训
- 不要反复用
firewall-cmd --direct写规则:该命令在 firewalld 0.6.6 上容易失败,导致 iptables-restore 报错,可能破坏现有规则 - 修改防火墙前先备份:
/etc/firewalld/zones/*.xml文件在 reload 时可能被覆盖,应先备份 - 不要同时直接编辑 XML 文件和用命令操作:这会导致 firewalld 内部状态和文件不一致
- Docker 和 firewalld 有潜在的 iptables 冲突:虽然正常情况下不会出问题,但在异常操作或启动顺序竞争时可能出现问题
- 排查问题前先确认当前状态:不要在问题已经自然恢复后再尝试复现,因为临时状态可能已经消失
8. 后续建议
- 如果问题再次出现,先不要做任何 firewalld 操作,立即检查:
iptables -t nat -L DOCKER -n(检查 DNAT 规则是否存在)iptables -L FORWARD -n --line-numbers(检查 Docker 规则位置)docker logs minio(检查容器日志)
- 如果 Docker 规则丢失,执行
sudo systemctl restart docker即可恢复 - 考虑将 firewalld 的启动顺序设置为在 Docker 之后,避免竞争条件
- 考虑在
/etc/firewalld/direct.xml中预先配置 Docker 相关的 FORWARD 规则作为兜底(但当前测试表明不需要)