找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2543

积分

1

好友

349

主题
发表于 昨天 07:25 | 查看: 5| 回复: 0

我计划在未来深入探讨Android的各个方面,不过今天我想先分享一个曾让我倍感困惑的问题,希望能帮助遇到同样困惑的开发者。这个问题并非Android独有,只是在Android容器环境下被我发现,它深刻地提醒了我:实际的路由复杂性远超乎通常的想象。

当你在Android设备(我使用的是容器环境)上运行 ip-route(8) 命令时,可能会惊讶地发现路由条目寥寥无几,甚至没有默认网关。这是因为,至少在我的Android容器中,Android并未使用主路由表(main)来配置路由。Linux内核实际上会为每个数据包查询多个路由表,我们可以通过 ip-rule(8) 命令来查看决定使用哪个路由表的规则。

查看我Android容器中的规则列表,内容如下:

0:      from all lookup local
10000:  from all fwmark 0xc0000/0xd0000 lookup legacy_system
11000:  from all iif lo oif eth0 uidrange 0-0 lookup eth0
16000:  from all fwmark 0x10063/0x1ffff iif lo lookup local_network
16000:  from all fwmark 0x10064/0x1ffff iif lo lookup eth0
17000:  from all iif lo oif eth0 lookup eth0
18000:  from all fwmark 0x0/0x10000 lookup legacy_system
19000:  from all fwmark 0x0/0x10000 lookup legacy_network
20000:  from all fwmark 0x0/0x10000 lookup local_network
23000:  from all fwmark 0x64/0x1ffff iif lo lookup eth0
31000:  from all fwmark 0x0/0xffff iif lo lookup eth0
32000:  from all unreachable

这比我日常使用的Fedora Silverblue系统上的规则复杂得多,后者通常只有三条基本规则:

0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

Android的规则数量几乎是普通桌面Linux系统的四倍。虽然我不完全清楚为何存在如此大的差异,但一个关键区别在于:Android的ip rule列表甚至不包含主路由表(main)。因此,要查看设备上完整的路由配置,通常需要同时查看所有路由表的内容。

幸运的是,ip 命令支持使用 all 作为一个伪表名来一次性显示所有路由表的信息。在我的容器中执行该命令的结果如下:

c340878bf6f5:/ # ip route show table all
172.17.0.0/16 dev eth0 table eth0_local proto static scope link
224.0.0.0/24 dev eth0 table eth0_local proto static scope link
default via 172.17.0.1 dev eth0 table eth0 proto static
172.17.0.0/16 dev eth0 table eth0 proto static scope link
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1
local 172.17.0.2 dev eth0 table local proto kernel scope host src 172.17.0.2
broadcast 172.17.255.255 dev eth0 table local proto kernel scope link src 172.17.0.2
fe80::/64 dev eth0 table eth0_local proto static metric 1024 pref medium
fe80::/64 dev eth0 table eth0 proto static metric 1024 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
local fe80::3fcd:8604:cea7:9ecd dev eth0 table local proto kernel metric 0 pref medium
multicast ff00::/8 dev eth0 table local proto kernel metric 256 pref medium

从这个输出中,我可以清晰地看到默认网关实际上定义在名为 eth0 的路由表中,而非主表。此外,通过这个输出,我们还可以提取出所有实际包含路由条目的表名(因为 ip-rule(8) 的输出可能会列出许多空表)。我使用了以下命令进行提取(可能不是最简洁的):

c340878bf6f5:/ # ip route show table all | grep -o "table [a-zA-Z_0-9]*" | cut -d' ' -f2 | sort | uniq
eth0
eth0_local
local

至此,谜团解开了。我终于明白为何在只查看主路由表时看不到默认网关,却依然能成功 ping 通外部地址——奥秘就在于Android利用了Linux内核强大的多路由表机制,通过复杂的规则(rule)将流量引导至正确的路由表(table)进行查找。这个案例也提醒我们,在进行网络问题排查时,尤其是在定制化较强的系统如Android上,需要更全面地检查路由规则和所有潜在的路由表。

希望这次在云栈社区分享的排查经历,能为你下次遇到类似网络路由问题时提供一个新的思路。

原文来源: https://yotam.net/posts/network-management-in-android-routing/




上一篇:前端面试深度解析:如何从架构和工程化角度阐述系统可扩展性?
下一篇:Web3支付白皮书:技术架构与稳定币应用
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-18 16:50 , Processed in 0.276316 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表