Android开发板与Windows网络不通?原来是策略路由在作祟
问题背景
最近在调试一个CCU Android开发板与Windows PC的网络连接问题。开发板通过USB网卡与Windows直连,之前使用192.168.103.x网段时一切正常,但切换到192.168.100.x网段后,双方竟然ping不通了!
问题现象
Windows ping Android板子:超时
Android板子 ping Windows:Network is unreachable
网络配置:Android板子IP为
192.168.100.17/24,Windows PC IP为192.168.100.10/24
排查过程
第一层:检查网络配置脚本
首先怀疑是网络配置脚本setup_android_net.sh没有更新到新网段。检查脚本发现:
# 原脚本内容 ip route add 192.168.100.0/24 dev eth0 ip route add default via 192.168.100.1 dev eth0发现问题:脚本里竟然没有给eth0设置IP地址!只有路由配置,没有ip addr add命令。
修复:在脚本中添加IP地址配置:
ip addr add 192.168.100.17/24 dev eth0执行后确认eth0有了正确的IP,但ping仍然不通。
第二层:确认Windows端配置
让用户在Windows端确认:
USB网卡已配置为
192.168.100.10/24防火墙已关闭或添加了例外规则
网络连接状态正常
Windows端配置正确,但问题依旧。
第三层:深入Android网络栈
执行ip rule show查看路由策略,发现了关键线索:
# Android策略路由规则(简化版) 0: from all lookup local 10000: from all fwmark 0xc0000/0xd0000 lookup legacy_system 13000: from all fwmark 0x10063/0x1ffff lookup local_network 15000: from all fwmark 0x0/0x10000 lookup legacy_system 16000: from all fwmark 0x0/0x10000 lookup legacy_network 17000: from all fwmark 0x0/0x10000 lookup local_network 23000: from all fwmark 0x0/0xffff uidrange 0-0 lookup main 32000: from all unreachable # 兜底规则,直接返回不可达!接着检查各个策略路由表的内容:
# 检查三个关键策略路由表 ip route show table local_network # 空的! ip route show table legacy_network # 空的! ip route show table legacy_system # 空的! # 检查main表(我们配置的路由在这里) ip route show table main # 输出:192.168.100.0/24 dev eth0 scope link src 192.168.100.17根本原因分析
Android策略路由机制
Android从5.0开始使用复杂的策略路由来支持多网络并发。与传统的Linux系统不同,Android不会直接使用main路由表,而是通过一系列策略路由表来决定数据包的走向。
路由表优先级对比
路由表 | 表ID | 说明 |
|---|---|---|
local | 255 | 系统自动维护,存放本地IP和广播地址路由 |
local_network | - | Android策略路由表,优先级较高 |
legacy_network | - | Android策略路由表,优先级中等 |
legacy_system | - | Android策略路由表,优先级较低 |
main | 254 | Linux默认路由表, |
default | 253 | 默认路由表 |
路由查找流程
Android的数据包路由查找顺序完全由ip rule show的输出决定:
规则0:先查
local表 → 没匹配(因为目标不是本地地址)规则10000-17000:查三个策略路由表(
local_network、legacy_network、legacy_system)→全部为空,没匹配规则23000:查
main表 →这里有我们的路由,但优先级太低!规则32000:
from all unreachable→直接返回"Network is unreachable"
关键问题:虽然我们在main表中正确配置了192.168.100.0/24 dev eth0,但Android的策略路由机制根本不会查到这个表,因为前面的策略路由表都是空的,数据包在匹配到main表之前就被unreachable规则拦截了。
问题总结
两个问题叠加导致网络不通:
脚本缺陷:初始脚本缺少
ip addr add命令,eth0没有IP地址Android特性:Android使用策略路由,需要将路由同时写入多个策略路由表
解决方案
修正网络配置脚本,同时解决两个问题:
#!/system/bin/sh # 修正后的setup_android_net.sh # 1. 设置IP地址(之前缺失的关键步骤) ip addr add 192.168.100.17/24 dev eth0 # 2. 在主路由表中添加路由(传统方式) ip route add 192.168.100.0/24 dev eth0 table main # 3. 在Android的三个策略路由表中都添加路由(关键!) ip route add 192.168.100.0/24 dev eth0 table local_network ip route add 192.168.100.0/24 dev eth0 table legacy_network ip route add 192.168.100.0/24 dev eth0 table legacy_system # 4. 添加默认路由(如果需要上网) ip route add default via 192.168.100.1 dev eth0 # 5. 刷新路由缓存 ip route flush cache # 6. 启动接口 ip link set eth0 up验证命令
执行修正后的脚本后,使用以下命令验证:
# 检查IP地址 ip addr show eth0 # 检查所有路由表 ip route show table main ip route show table local_network ip route show table legacy_network ip route show table legacy_system # 测试连通性 ping -c 4 192.168.100.10 # 查看路由决策过程 ip route get 192.168.100.10经验总结
Android网络配置的特殊性:Android不是标准的Linux,它的网络栈经过深度定制,特别是策略路由机制。
路由表要写全:在Android上配置网络时,不能只写
main表,还要考虑策略路由表。排查思路:
先检查基础配置(IP地址、接口状态)
再检查路由表(
ip route show)关键步骤:检查路由策略(
ip rule show)和各策略路由表
调试命令组合:
# 快速诊断网络问题 ip addr show # 查看IP配置 ip route show # 查看主路由表 ip rule show # 查看路由策略 ip route show table <表名> # 查看特定路由表 ip route get <目标IP> # 查看具体路由决策脚本健壮性:网络配置脚本应该包含完整的配置步骤,特别是容易被忽略的
ip addr add。
扩展知识
Android策略路由表的作用
local_network:处理本地网络流量
legacy_network:处理传统网络应用的流量
legacy_system:处理系统服务的网络流量
这些表的存在使得Android能够为不同应用、不同UID、不同网络标记(fwmark)的数据包提供不同的路由路径,实现精细化的网络管理。
为什么Android要这样设计?
Android作为移动操作系统,需要同时处理:
蜂窝数据(4G/5G)
WiFi
以太网
VPN
热点共享
策略路由机制让Android能够根据数据包的来源、目的、标记等因素,智能地选择最佳的网络路径,实现多网络并发和网络切换的无缝体验。
结语
这次排查经历再次证明:了解系统底层机制的重要性。表面上看是简单的网络不通问题,深挖下去却是Android策略路由机制在"作祟"。希望这篇分享能帮助遇到类似问题的开发者少走弯路。
记住:在Android上配网络,别忘了策略路由表!
