路由器 H3C GR-3000AX-U 不支持NAT回流
核心问题定位
- 外网访问
- ✅ 非Docker服务(直接运行在宿主机上的服务)可以访问
- ❌ Docker服务 无法访问
- 内网访问
- ✅ 内网IP访问(无论Docker还是非Docker)正常
- ❌ 内网通过公网IP访问 全部失败(符合NAT回环不支持的预期)
结论 :
Docker 的端口映射与路由器的端口转发存在冲突,导致外网无法访问 Docker 服务,而内网访问 Docker 正常是因为直接走了内网IP,不依赖端口转发。
根本原因分析
1. Docker 默认使用 bridge
网络(NAT 模式)
当您运行:
bash
docker run -p 8080:80 nginx
Docker 会在 iptables
里添加 NAT 规则 ,使宿主机的 8080
端口流量转发到容器的 80
端口。
但问题在于:
- 外网流量进入宿主机后,Docker 的 NAT 规则可能没有正确处理(特别是源IP是外网时)。
- 路由器的端口转发目标必须是宿主机的IP+端口 ,但 Docker 的
bridge
网络可能会导致流量被错误丢弃。
2. 路由器端口转发 vs. Docker 端口映射
流量方向 | 正常流程 | 可能的问题 |
---|---|---|
外网 → 路由器 → 宿主机 → Docker | 路由器转发到 宿主机IP:8080 → Docker 再转发到容器 |
Docker 的 iptables 规则可能未允许外网IP的流量 |
内网 → 宿主机 → Docker | 直接访问 宿主机IP:8080 → Docker 转发正常 |
不依赖路由器,所以没问题 |
解决方案
改用 host
网络模式(推荐)
让 Docker 直接使用宿主机的网络栈,避免 NAT 问题:
bash
docker run --network=host -d nginx
优点:
- 容器直接绑定到宿主机端口,不再经过 Docker NAT。
- 路由器的端口转发会直接生效(就像非Docker服务一样)。
缺点:
- 容器会占用宿主机的网络栈(多个容器不能绑定相同端口)。
总结表
现象 | 原因 | 解决方案 |
---|---|---|
外网无法访问Docker,但非Docker服务正常 | Docker NAT 规则干扰 | 改用 host 模式 |
内网访问公网IP失败 | 路由器不支持 NAT 回环 | 1. 内网直接用内网IP访问 |
请先尝试 --network=host
,如果问题解决,则确认是 Docker NAT 问题。