# 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 链添加放行规则时: 1. 多次执行 `--direct --add-rule` 失败,报错 `iptables-restore: line 2 failed` 2. 直接编辑 `/etc/firewalld/direct.xml` 文件,导致规则不一致 3. 执行 `firewall-cmd --reload` 后,`/etc/firewalld/zones/public.xml` 被覆盖为只剩 ``,所有端口和规则丢失 4. **22 端口被锁,SSH 无法连接**(用户通过 RustDesk 远程桌面仍可操作) ### 2.6 恢复防火墙配置 1. 从 `/etc/firewalld/zones/public.xml.old` 恢复了完整的端口列表和服务 2. 在恢复的 public.xml 中添加了 `` 3. 清空了 direct.xml(删除了之前添加的 FORWARD 规则) 4. 重启 firewalld,所有端口恢复正常 ### 2.7 修改 MinIO 配置 从 docker-compose.yml 中删除了以下两行: ```yaml 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 链。 **操作**: 1. 删除手动添加的 FORWARD_direct 规则 2. 执行 `firewall-cmd --reload` **结果**:9000 端口仍然可以访问。Docker 的 nat 表 DNAT 规则和 filter 表 FORWARD/DOCKER 链规则在 reload 后**没有被清掉**。 ### 3.2 尝试二:停 Docker → reload firewalld → 启 Docker **假设**:Docker 和 firewalld 的启动顺序会影响 iptables 规则的排列位置。 **操作**: 1. `sudo systemctl stop docker` 2. `sudo firewall-cmd --reload` 3. `sudo 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` 导致的。 **操作**: 1. 还原 docker-compose.yml 中的 `MINIO_SERVER_URL` 和 `MINIO_BROWSER_REDIRECT_URL` 2. 重启 MinIO 容器 3. 不动防火墙,直接测试 **结果**: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. 未查明的原因 综合以上分析,**真正的原因未能确定**。可能的原因包括: 1. **Docker 和 firewalld 的启动顺序竞争**:某次系统重启后,firewalld 在 Docker 之后启动,清掉了 Docker 的 iptables 规则,而 Docker 没有自动恢复 2. **iptables 异常状态**:某次 firewalld 操作(如 reload 或 direct 规则添加失败)导致 iptables 处于不一致状态,Docker 的规则部分丢失 3. **MinIO 配置叠加效应**:`MINIO_SERVER_URL=http://127.0.0.1:9000` 在某些情况下可能导致 MinIO 拒绝非本地请求,使端口扫描工具误判端口关闭 4. **临时网络问题**:可能是当时的临时网络或路由问题,后续自然恢复 ## 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. 经验教训 1. **不要反复用 `firewall-cmd --direct` 写规则**:该命令在 firewalld 0.6.6 上容易失败,导致 iptables-restore 报错,可能破坏现有规则 2. **修改防火墙前先备份**:`/etc/firewalld/zones/*.xml` 文件在 reload 时可能被覆盖,应先备份 3. **不要同时直接编辑 XML 文件和用命令操作**:这会导致 firewalld 内部状态和文件不一致 4. **Docker 和 firewalld 有潜在的 iptables 冲突**:虽然正常情况下不会出问题,但在异常操作或启动顺序竞争时可能出现问题 5. **排查问题前先确认当前状态**:不要在问题已经自然恢复后再尝试复现,因为临时状态可能已经消失 ## 8. 后续建议 1. 如果问题再次出现,**先不要做任何 firewalld 操作**,立即检查: - `iptables -t nat -L DOCKER -n`(检查 DNAT 规则是否存在) - `iptables -L FORWARD -n --line-numbers`(检查 Docker 规则位置) - `docker logs minio`(检查容器日志) 2. 如果 Docker 规则丢失,执行 `sudo systemctl restart docker` 即可恢复 3. 考虑将 firewalld 的启动顺序设置为在 Docker 之后,避免竞争条件 4. 考虑在 `/etc/firewalld/direct.xml` 中预先配置 Docker 相关的 FORWARD 规则作为兜底(但当前测试表明不需要)