Appearance
微服务访问报 No route to host:一次 firewalld 端口未放行问题排查
一、问题背景
环境中存在两台 ECS:
机器 A
- 公网 IP:
114.xx.xx.xx - 内网 IP:
172.16.0.41
- 公网 IP:
机器 B
- 公网 IP:
47.xx.xx.xx - 内网 IP:
172.16.0.42
- 公网 IP:
部署服务及端口:
- gateway:
8080 - oa-global:
9206 - oa-system:
9202
请求流程:
text
浏览器
↓
gateway
↓
通过 Nacos 获取服务内网 IP
↓
转发至目标微服务二、问题现象
1. gateway 日志报错
两台机器上的 gateway 在跨节点访问 oa-global 时均出现:
text
No route to host 172.16.0.xx:9206例如:
172.16.0.41上的 gateway 访问172.16.0.42:9206失败172.16.0.42上的 gateway 访问172.16.0.41:9206失败
2. 本机访问正常,跨机器访问失败
表现为:
- gateway 访问本机服务端口正常
- gateway 访问另一台机器相同服务端口失败
3. 对比端口连通性
对两个服务端口进行对比:
9202(oa-system):两台机器互通9206(oa-global):两台机器互不通
说明两台 ECS 之间的内网并非整体不通,问题更可能集中在 9206 端口。
4. telnet 验证
分别执行:
bash
telnet 172.16.0.41 9206
telnet 172.16.0.42 9206均返回:
text
No route to host公网 IP 的 9202、9206 均未开放,本次服务间通信本身使用的是 ECS 内网地址,因此继续从内网端口连通性方向排查。
三、为什么防火墙问题会表现为 No route to host
看到:
text
No route to host很容易第一时间理解为:
当前机器没有到目标 IP 的网络路由。
但这个错误并不只会在“真的没有路由”时出现。
Linux 应用通过 Socket 建立 TCP 连接时,底层网络错误最终会以 errno 的形式返回给应用程序。No route to host 通常对应:
text
EHOSTUNREACH即:
text
Host is unreachable真正的“没有路由”确实可能产生这个错误,例如:
- 路由表中没有到目标网络的路由
- 网关不可达
- 网络设备无法找到目标主机
但防火墙主动拒绝连接时,也可能产生相同的上层表现。
例如目标服务器上的防火墙规则并不是简单地丢弃数据包,而是使用 REJECT 拒绝请求。此时防火墙可能向请求方返回 ICMP 错误报文。
请求方的 Linux 网络栈收到这类 ICMP 错误后,会把它转换成 Socket 层错误,应用最终就可能看到:
text
No route to host因此:
text
No route to host不能简单理解成:
text
一定是路由表有问题更准确的理解应该是:
当前 TCP 连接无法到达目标主机或目标网络,具体原因还需要继续判断。
在实际排查中,可以结合现象快速缩小范围。
本次问题中:
172.16.0.41与172.16.0.42之间其他端口可以正常通信9202可以跨机器访问- 只有
9206无法访问 9206服务本身已经正常监听- 两台机器的
firewalld都处于启用状态
因此基本可以排除“两台机器之间不存在路由”的可能。
如果真的是 ECS 内网路由问题,那么通常不会只影响:
text
9206而:
text
9202却可以正常访问。
这种“同一目标 IP,部分端口正常、部分端口报 No route to host”的现象,应该优先检查:
- 主机防火墙
- 云安全组
- 网络 ACL
- 服务监听地址
而不是首先修改系统路由表。
本次最终确认,原因就是目标节点的 firewalld 未放行:
text
9206/tcp四、排查过程
1. 确认服务监听状态
执行:
bash
ss -lntp | grep 9206两台机器均确认 Java 进程已经监听 9206 端口。
这里除了确认进程存在,还需要关注具体监听地址。
如果服务只监听:
text
127.0.0.1:9206那么即使防火墙已经放行,其他机器仍然无法访问。
跨主机提供服务时,通常应该监听类似:
text
0.0.0.0:9206或者直接监听对应的内网地址。
本次环境中的服务监听正常,因此继续排查主机网络策略。
2. 确认 firewalld 状态
执行:
bash
systemctl status firewalld两台机器的 firewalld 均处于 active 状态。
3. 确认当前活动 zone
在修改防火墙规则之前,可以先执行:
bash
firewall-cmd --get-active-zones确认网卡实际使用的 zone。
本次环境使用的是 public zone。
4. 对比防火墙端口放行情况
分别执行:
bash
firewall-cmd --zone=public --list-ports机器 A 未发现:
text
9206/tcp机器 B 同样未发现:
text
9206/tcp此时基本可以确认,oa-global 服务虽然已经正常监听 9206,但两台机器的 firewalld 都没有允许其他节点访问该端口。
五、根因
两台 ECS 上的 oa-global 均正常监听 9206 端口,但 firewalld 没有放行 9206/tcp。
因此:
- 本机访问不经过跨主机网络入口,可以正常访问
- 跨节点访问目标机器的
9206时,被目标机器的防火墙规则拒绝 - gateway 最终表现为:
text
No route to host需要注意的是:
No route to host并不一定意味着 Linux 路由表真的不存在目标路由。
在某些防火墙拒绝连接的场景中,客户端同样可能收到类似 No route to host 的错误,因此不能只根据错误文本直接判断为路由故障。
六、解决方案
在两台机器上分别放行 oa-global 使用的 9206/tcp。
以下命令假设对应网卡使用的是 public zone:
bash
firewall-cmd --zone=public --add-port=9206/tcp --permanent
firewall-cmd --reload执行后再次确认:
bash
firewall-cmd --zone=public --list-ports应能够看到:
text
9206/tcp七、验证结果
重新测试:
bash
telnet 172.16.0.41 9206
telnet 172.16.0.42 9206结果均恢复正常。
同时:
- gateway 跨节点访问恢复
oa-global调用正常- 日志中不再出现
No route to host
八、经验总结
这次问题的特点是:
本机访问正常,但相同服务跨机器访问失败。
遇到类似现象时,可以依次确认:
- 服务进程是否正常运行
- 服务是否监听在正确地址,而不是仅监听
127.0.0.1 - 目标端口是否被主机防火墙放行
- 云平台安全组是否允许对应流量
- 网络 ACL、路由等更底层网络策略是否存在限制
另外,同一组微服务节点的防火墙规则应尽量保持一致,否则很容易出现:
text
A → B 正常
B → A 失败或者不同服务端口表现不一致的问题。
九、改进建议
- 使用自动化脚本统一维护各节点防火墙规则
- 定期巡检节点的
firewalld配置,避免配置漂移 - 在服务上线 checklist 中增加端口连通性检查
- 新增服务端口时,同时确认监听地址、主机防火墙和云安全组配置