一、系统架构总览
应用层
├─ ConnectivityManager API
│ ├─ requestNetwork()
│ ├─ setProcessDefaultNetwork()
│ └─ bindProcessToNetwork()
└─ Socket APIs
├─ SO_BINDTODEVICE
├─ SO_MARK (fwmark)
└─ IP_PKTINFO
↓ IPC (Binder)
系统层 (frameworks_base)
├─ ConnectivityService
│ └─ 网络生命周期管理
├─ NetworkPolicyManagerService
│ └─ 流量限制策略
└─ RoutingCoordinatorService
└─ 高层路由协调
↓ IPC (Binder)
netd 层 (system_netd) - C++ 实现
├─ RouteController
│ ├─ 策略路由规则 (Policy-based Routing)
│ ├─ 路由表管理
│ └─ 接口转发
├─ NetlinkCommands
│ └─ netlink socket 通信
└─ Fwmark/FwmarkCommand
└─ Socket 标记管理
↓ netlink socket
Linux Kernel (5.x+)
├─ netlink 子系统
├─ 路由表 (main, local, per-interface tables)
├─ 策略路由规则库 (FIB rules)
├─ iptables/nftables 防火墙
└─ 网络栈 (TCP/IP, IPv6等)
二、核心组件详解
2.1 Fwmark 标记系统
位置:system_netd/include/Fwmark.h
作用:对 socket 进行标记,用于策略路由决策
struct Fwmark {
// 位字段定义
uint32_t netId : 16; // 网络ID (0-65535)
uint32_t explicitlySelected : 1; // 是否明确选择网络
uint32_t protectedFromVpn : 1; // 是否受 VPN 保护
uint32_t permission : 2; // 权限标记 (NONE/SYSTEM/INTERNET等)
uint32_t reserved : 12; // 保留位
uint32_t intValue; // 用于内核操作
};
标记的应用:
- 进程级标记 - 通过 setsockopt(SO_MARK) 标记 socket
- 进制数据包标记 - iptables MARK 规则标记入站数据包
- 路由决策 - 内核根据标记选择路由表
2.2 策略路由规则系统
文件:system_netd/server/RouteController.cpp
规则优先级(从高到低):
// 规则优先级
RULE_PRIORITY_LOCAL_ROUTES = 9000
RULE_PRIORITY_SECURE_VPN = 10000
RULE_PRIORITY_BYPASSABLE_VPN_* = 11000-12000
RULE_PRIORITY_VPN_OVERRIDE_* = 13000-14000
RULE_PRIORITY_EXPLICIT_NETWORK = 16000
RULE_PRIORITY_UID_EXPLICIT_NETWORK = 17000-18000
RULE_PRIORITY_IMPLICIT_NETWORK = 19000
RULE_PRIORITY_UID_IMPLICIT_NETWORK = 20000-21000
RULE_PRIORITY_OUTPUT_INTERFACE = 22000
RULE_PRIORITY_UID_LOCAL_ROUTES = 23000
RULE_PRIORITY_LOCAL_NETWORK = 24000
RULE_PRIORITY_LEGACY_SYSTEM = 25000
RULE_PRIORITY_VPN_FALLTHROUGH = 26000
RULE_PRIORITY_LEGACY_NETWORK = 27000
RULE_PRIORITY_MAIN = 32000
关键规则示例:
// 1. VPN UID 范围规则
modifyVpnUidRangeRule(table, uidStart, uidEnd, priority, secure, add)
→ rtnetlink RTM_NEWRULE/RTM_DELRULE
→ 匹配条件: fwmark (protectedFromVpn), UID range
→ 指向: VPN 路由表
→ 作用: 将 UID 范围内的流量路由到 VPN
// 2. 显式网络选择规则
modifyExplicitNetworkRule(netId, table, permission, uidStart, uidEnd)
→ rtnetlink RTM_NEWRULE/RTM_DELRULE
→ 匹配条件: fwmark (netId, explicitlySelected), UID range, permission
→ 指向: 网络专用路由表
→ 作用: 应用显式选择的网络
// 3. 隐式网络规则
modifyImplicitNetworkRule(netId, table)
→ rtnetlink RTM_NEWRULE/RTM_DELRULE
→ 匹配条件: fwmark (netId, !explicitlySelected)
→ 指向: 网络专用路由表
→ 作用: connect() 时绑定的网络
2.3 网络接口路由表管理
每个物理网络接口对应一个路由表:
接口: wlan0 → 路由表: 10000
接口: rmnet0 → 路由表: 10001
接口: eth0 → 路由表: 10002
计算方式: table_id = interface_index + ROUTE_TABLE_OFFSET_FROM_INDEX
路由表类型:
├─ Global table (主表)
│ └─ 用于 unicast routes, default route 等
├─ Local table (<interface>_local)
│ └─ 用于本地连接路由
└─ 特殊表
├─ RT_TABLE_LOCAL (255) - 本地路由
├─ RT_TABLE_MAIN (254) - 主路由表
├─ ROUTE_TABLE_LOCAL_NETWORK (97) - 本地网络特殊路由
├─ ROUTE_TABLE_LEGACY_NETWORK (98) - 遗留网络
└─ ROUTE_TABLE_LEGACY_SYSTEM (99) - 遗留系统
三、路由决策流程
Socket 创建:
↓
socket() → 内核分配 socket
↓
setsockopt(SO_MARK) 或自动标记
↓
fwmark 设置:
├─ app 显式选择: explicitlySelected = 1
├─ app 隐式绑定: explicitlySelected = 0
├─ 权限检查: permission 字段
├─ VPN 保护: protectedFromVpn 字段
└─ 网络ID: netId 字段
connect()/send():
↓
内核查询 FIB 规则:
1. 遍历规则表 (按优先级从高到低)
2. 匹配规则条件 (fwmark, UID, IIF等)
3. 第一条匹配 → 使用指定的路由表
路由表选择逻辑:
├─ VPN 保护 && 在 VPN UID 范围
│ → 路由绕过 VPN
├─ 显式选择网络 && 权限检查通过
│ → 使用选定网络的路由表
├─ 连接到默认网络
│ → 使用默认网络的路由表
└─ 无匹配规则
→ 使用主路由表 (main)
路由查找 (查询路由表):
1. 最长前缀匹配 (Longest Prefix Match)
2. 查找目标 IP 对应的路由条目
3. 获得下一跳或出接口
4. 可选: 根据 MTU/priority 调整
发送数据包:
├─ 源地址选择
├─ ARP 解析 (IPv4)
├─ 邻接表查找
└─ 驱动级发送
四、路由表的生命周期
1. 接口连接时:
ConnectivityService 通知 netd
↓
RouteController.createPhysicalNetwork()
↓
为接口分配路由表 ID
2. 获得 IP 地址时:
DHCP/RA 获得 IP
↓
RouteController.addRoute()
↓
添加路由条目到接口路由表
├─ 直连路由 (connected routes)
├─ 默认路由 (default route)
└─ 其他静态路由
3. 网络切换时:
新网络成为默认
↓
RouterController.updateDefaultNetwork()
↓
修改策略规则优先级
├─ 旧网络隐式规则优先级降低
└─ 新网络隐式规则优先级提升
4. 接口断开时:
ConnectivityService 通知 netd
↓
RouteController.destroyPhysicalNetwork()
↓
清理所有规则和路由:
├─ RouteController.flushRoutes(interface)
├─ RouteController.removeInterfaceFromNetwork()
└─ RouteController.removeUsersFromNetwork()
五、特殊场景处理
5.1 VPN 分隧道 (Split Tunnel)
VPN 未拦截流量的处理:
1. VPN 指定 underlying networks:
declaredUnderlyingNetworks = {network1, network2}
2. 创建 fallthrough 规则:
modifyVpnFallthroughRule()
├─ VPN netId 的规则
├─ 如果 VPN 表中无路由
├─ 则查询 underlying network 的路由表
└─ 允许流量绕过 VPN
3. 数据流:
源地址 → VPN fwmark → VPN 表查询
├─ 有匹配路由 → 通过 VPN
└─ 无匹配路由 → fallthrough 规则 → underlying network 表
5.2 NAT64 (464xlat)
IPv6-only 网络上的 IPv4 支持:
Nat464Xlat 流程:
1. 检测网络类型: IPv6 only + 无 IPv4
2. NAT64 前缀发现:
├─ Router Advertisement (RA) 中的前缀
├─ DNS 查询 (RFC 7050 - well-known prefix)
└─ 默认前缀: 64:ff9b::/96
3. 启动 clatd 守护进程:
├─ 创建虚拟 TUN 接口 (v4-<iface>)
├─ 配置 IPv4 地址 (192.0.0.4)
├─ 翻译 IPv4 ↔ IPv6 数据包
└─ 管理路由规则
4. 路由配置:
IPv4 流量 (0.0.0.0/0)
├─ 进入 v4-wlan0 interface
├─ clatd 翻译成 IPv6
├─ 通过原始网络发送
└─ 响应翻译回 IPv4
5.3 多播路由 (Multicast Routing)
MulticastRoutingCoordinatorService:
1. 添加虚拟接口 (MIF):
├─ 映射物理接口 → 虚拟索引
├─ 最多 32 个虚拟接口
└─ 通过 setsockopt(MRT6_ADD_MIF) 配置
2. 多播转发缓存 (MFC):
MFC Key: (incoming interface, source address, group address)
MFC Value: {outgoing interfaces, last used time}
作用: 决定组播数据包转发方向
3. 配置模式:
├─ FORWARD_NONE - 不转发
├─ FORWARD_WITH_MIN_SCOPE - 基于作用域转发
└─ FORWARD_SELECTED - 选择特定组地址转发
4. 组播组管理:
├─ JOIN: 表示对该组的兴趣
├─ LEAVE: 停止接收
└─ NOCACHE: kernel upcall 触发 MFC 添加
六、调试和监测
# 查看所有路由规则
adb shell ip rule list [all]
# 查看特定路由表
adb shell ip route show table <table_id>
adb shell ip route show table wlan0
adb shell ip route show table all
# 查看 netid 对应的路由表
adb shell netd list_table_for_interface <iface>
# 跟踪 socket 标记
adb logcat | grep -i fwmark
adb logcat | grep -i "RouteController"
# 查看连接状态
adb shell ss -tlnp | grep -E ":(80|443)"
adb shell netstat -an | grep ESTABLISHED
# 网络命名空间操作
adb shell ip netns list
adb shell ip netns exec <netns> ip route show
# dumpsys 查看路由状态
adb shell dumpsys connectivity --verbose
# 实时路由追踪
adb shell tcpdump -i any -n "host <ip>"
七、Android 15 路由改进
新特性:
├─ eBPF 路由策略强化
│ └─ 基于 BPF programs 的高性能路由
├─ 网络切片支持
│ ├─ 5G URSP (UE Route Selection Policy)
│ ├─ Traffic Descriptor 匹配
│ └─ NSSAI (Network Slice Selection)
├─ 改进的 VPN 支持
│ ├─ 应用级 VPN 选择
│ ├─ VPN 网络隔离
│ └─ 更精细的权限控制
└─ 性能优化
├─ 缓存优化
├─ 规则合并
└─ 内核-用户态交互优化
这个分析涵盖了 Android 路由系统从应用层到内核层的完整技术栈,包括策略路由、特殊场景处理和调试方法。