news 2026/7/9 1:07:33

Android 7系统网络(二)内核层—netfilter_iptables与路由策略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android 7系统网络(二)内核层—netfilter_iptables与路由策略

系列目录:第一篇:全景图与调用链路概览 |第二篇:内核层—netfilter/iptables与路由策略| 第三篇:Native层(上)—netd守护进程与CommandListener | 第四篇:Native层(下)—netd Controller详解 | 第五篇:Framework层(上)—ConnectivityService核心机制 | 第六篇:Framework层(下)—NMS/NPMS/NSS三大服务 | 第七篇:连接建立—WiFi/移动数据/以太网完整流程 | 第八篇:应用API层—ConnectivityManager使用与实战调试


一、为什么内核层是关键

Android 的网络能力建立在 Linux 内核之上。理解下列内核机制,才能弄懂 netd 和各种 Controller 到底在操作什么:

  • netfilter / iptables:防火墙、NAT、数据包过滤——几乎所有网络安全和共享功能的基础
  • 路由表与策略路由:多网络并存时,每个网络需要独立的路由表
  • fwmark:Socket 标记机制,决定数据包走哪张路由表

本章直接从内核视角拆解这些基础设施,后续所有关于 netd Controller 的分析都将引用此处的概念。


二、netfilter 框架

2.1 五链四表

netfilter 是 Linux 内核中的一个数据包过滤框架,定义了五个钩子点(Hook)和四张表(Table)

网络层数据包流向: 入口 本机进程 出口 │ ▲ │ ▼ │ │ PREROUTING ──────────→ routing ──────────→ FORWARD ─┐ │ │ │ │ │ ▼ │ │ │ INPUT │ │ │ │ │ │ │ 本机进程接收 │ │ │ │ │ │ 本机进程发送 │ │ │ │ │ │ └────────────────── routing ◄────────────────┘ │ │ │ ▼ │ OUTPUT ──────────→ POSTROUTING │ ▼ 出口

关键:数据包在内核中沿着这五个钩子点依次穿行,每个钩子点都可以挂载 iptables 规则链——Android 正是利用这些钩子点来实现防火墙、NAT 共享和 DNS 拦截。

五个 Hook 点的含义:

Hook触发时机典型用途
PREROUTING数据包进入网络栈后立刻触发DNAT(目的地址转换)、入口流量过滤
INPUT数据包路由到本机后触发本机入站防火墙
FORWARD数据包不是发给本机时触发路由器上的转发过滤(网络共享的关键)
OUTPUT本机发出的数据包触发本机出站防火墙
POSTROUTING数据包即将离开网络栈时触发SNAT(源地址转换)、MASQUERADE

四张表的用途:

表名用途内建链
filter过滤数据包(允许/拒绝)INPUT, FORWARD, OUTPUT
nat网络地址转换PREROUTING, INPUT, OUTPUT, POSTROUTING
mangle修改数据包内容(如 TTL、TOS)全部五链
raw设置连接跟踪豁免PREROUTING, OUTPUT

2.2 Android 对 netfilter 的使用

Android 大量使用 iptables 来实现各种网络功能。adb shell iptables -t nat -L -n查看一个典型设备上的规则,会发现大量由 netd 自动生成的规则:

  • 网络共享(Tethering):在 nat 表的 POSTROUTING 链中添加 MASQUERADE 规则,实现类似路由器的 NAT
  • 防火墙:在 filter 表的 OUTPUT 链中根据 UID 拒绝/允许出站流量(uid_owner 匹配)
  • DNS 拦截:将 DNS 请求(UDP 53)重定向到 netd 的 dnsproxyd socket

三、Android 中的 iptables 命令详解

3.1 nat_controller 的网络共享规则

源码路径system/netd/server/TetherController.cpp

当开启 WiFi 热点时,netd 的 TetherController 会执行:

# 启用 IP 转发echo1>/proc/sys/net/ipv4/ip_forward# 添加 NAT 规则(MASQUERADE)iptables-tnat-APOSTROUTING-ormnet_data0-jMASQUERADE# 添加 FORWARD 规则(允许转发)iptables-AFORWARD-iwlan0-ormnet_data0-jACCEPT iptables-AFORWARD-irmnet_data0-owlan0-mstate--stateESTABLISHED,RELATED-jACCEPT

关键:MASQUERADE 是一种特殊的 SNAT——自动替换源 IP 为出口接口的 IP,是移动热点的核心技术。FORWARD 链的ESTABLISHED,RELATED规则确保只有已建立连接的返回流量能通过,避免未授权的入站访问。

3.2 firewall_controller 的 UID 过滤

源码路径system/netd/server/FirewallController.cpp

网络防火墙的核心是对每个 UID 的规则控制:

# 禁止 UID 10086 使用 WiFiiptables-AOUTPUT-owlan0-mowner --uid-owner10086-jREJECT# 禁止 UID 10086 使用移动数据iptables-AOUTPUT-ormnet_data0-mowner --uid-owner10086-jREJECT# 省电模式下禁止所有后台应用使用移动数据iptables-Abw_costly_rmnet_data0-mowner --uid-owner10086-jREJECT

关键-m owner --uid-owner匹配器是 Android 内核中的扩展模块(xt_owner),根据发起 socket 的进程 UID 匹配数据包。这使得 Android 能以进程粒度控制网络访问,而非传统 Linux 的 IP/端口粒度。

-m owner --uid-owner匹配器是 Android 内核中的一个扩展模块(xt_owner),根据发起 socket 的进程 UID 匹配数据包。

3.3 DNSPROXYLISTENER 的 DNS 重定向

netd 中的 DnsProxyListener 通过 iptables 将所有的 DNS 请求重定向到 netd 的 DNS 代理端口:

源码路径system/netd/server/DnsProxyListener.cpp

# 拦截 WiFi 上的 DNS 请求,重定向到 netd 的 dnsproxyd socketiptables-tnat-AOUTPUT-pudp--dport53-jDNAT --to-destination127.0.0.1:53# 实际上 netd 在本地监听 UDP 53 端口(通过 dnsproxyd socket)

关键:DNS 拦截是 Android 网络管理的核心机制——通过将 UDP 53 端口的流量统一重定向到 netd,Android 得以按网络接口(WiFi/移动数据/VPN)使用不同的上游 DNS 服务器,并实现统一的 DNS 缓存。

通过 DNS 拦截,Android 能够:

  • 统一管理 DNS 缓存
  • 根据不同网络接口使用不同的 DNS 服务器
  • 在 VPN 连接时使用 VPN 的 DNS

四、路由表与策略路由

4.1 传统路由表 vs Linux 策略路由

传统路由表只有一个(main),所有数据包都用同一张表决定出口。但 Android 需要支持多网络并存,所以使用了 Linux 的策略路由机制:

传统路由: 数据包 → 查 main 路由表 → 走默认路由 → 一个网络出口 策略路由(Android) 数据包 → 根据 fwmark 查 rule → 转到 netId 对应的路由表 → 使用该网络的出口

关键:传统路由是"一条路走到黑",策略路由是"看标记选路"——fwmark 就是那个标记,内核根据它决定查询哪张路由表,从而让 WiFi 和移动数据的流量各走各的路。

4.2 Android 的路由表组织

源码路径system/netd/server/RouteController.cpp

每个网络类型分配一个独立的 netId 和对应的路由表:

路由表 netId 网络类型 物理接口 ───────────────────────────────────────── 99 99 本地/回环 lo 100 100 WiFi wlan0 101 101 移动数据 rmnet_data0 102 102 VPN tun0 ...

关键:路由表编号与 netId 一一对应,这个映射关系由RouteController/data/misc/net/rt_tables文件中维护,确保每个物理网络有独立的路由命名空间。

每个路由表的内容大致如下(以 WiFi 为例)

# 路由表 100 的内容iproute show table100# 直连路由(本网段)192.168.1.0/24 dev wlan0 proto kernel scopelinksrc192.168.1.100# 默认路由default via192.168.1.1 dev wlan0 proto static

关键:每张路由表至少包含两条路由——直连路由(link scope)负责本网段通信,默认路由(default)负责所有其他流量。RouteController通过 netlink socket 直接向内核写入这些路由条目。

4.3 fwmark 机制

fwmark(Firewall Mark)是 Linux 内核中为 Socket 打标记的机制。Android 利用它来选择路由表。

源码路径system/netd/server/RouteController.cpp

// RouteController 中的路由优先级定义constuint32_tRULE_PRIORITY_VPN_OVERRIDE_SYSTEM=10000;constuint32_tRULE_PRIORITY_VPN_OVERRIDE_OIF=10500;constuint32_tRULE_PRIORITY_VPN_OUTPUT_TO_LOCAL=11000;constuint32_tRULE_PRIORITY_SECURE_VPN=12000;constuint32_tRULE_PRIORITY_PROHIBIT_NON_VPN=12500;

关键:优先级数值越小越优先匹配。VPN 相关规则(10000-12500)排在前面,确保 VPN 流量优先于普通网络流量被路由;PROHIBIT_NON_VPN(12500)则在安全 VPN 模式下主动丢弃未走 VPN 的数据包。

策略路由规则通过ip rule命令配置:

# 查看当前策略路由规则iprule show# 典型输出:# 0: from all lookup local → 本地表(最高优先级)# 10000: from all fwmark 0x3e8 lookup 1000 → 直连路由保护# 10500: from all fwmark 0x3e8/0xc0000 lookup 1000 → VPN 优先# 11000: from all fwmark 0x3e8/0xc0000 lookup local → VPN 到本地# 12000: from all fwmark 0x10064/0x1ffff lookup 100 → WiFi 网络(netId=100)# 13000: from all fwmark 0x20065/0x1ffff lookup 101 → 移动数据(netId=101)# ...

关键:每条策略路由规则由fwmark/掩码匹配条件决定——0x10064/0x1ffff中的0x10064提取出 netId=100 和权限位,0x1ffff掩码确保只匹配低 17 位,从而精确区分不同网络的数据包。

fwmark 的计算方式由Fwmark.h中的位域定义:

源码路径system/netd/include/Fwmark.h

unionFwmark{uint32_tintValue;struct{unsignednetId:16;// 网络 ID(低 16 位)boolexplicitlySelected:1;// 是否显式选择boolprotectedFromVpn:1;// 是否受 VPN 保护Permission permission:2;// 权限位(18-19 位)};};

关键Fwmark是一个 32 位 union——同一个intValue可以按位域拆解出 netId、选择标志、VPN 保护和权限四个字段,内核的ip rule匹配时直接使用intValue与掩码做按位比较。

fwmark = netId | (explicitlySelected << 16) | (protectedFromVpn << 17) | (permission << 18) 权限位: PERMISSION_NONE = 0x0 // 普通应用 PERMISSION_NETWORK = 0x1 // 特权网络应用 PERMISSION_SYSTEM = 0x3 // 系统应用(包含 NETWORK 权限)

关键:权限位位于 fwmark 的高位(18-19),确保系统应用(PERMISSION_SYSTEM = 0x3)的 fwmark 值始终大于普通应用,配合策略路由的优先级匹配可以实现"系统应用可绕过某些网络限制"的效果。

示例:

  • WiFi 的 netId=100,普通应用:fwmark =0x00000064
  • 移动数据的 netId=101,系统应用:fwmark =0x000C0065(permission=0x3 << 18)

每个 Socket 创建时可以通过setsockopt(SO_MARK)设置 fwmark,或在 connect 前调用bindServiceInfo()(Android 特有)来绑定到特定网络。


五、网络接口管理

5.1 Linux 网络接口

Android 设备上常见的网络接口:

接口名类型说明
lo回环127.0.0.1
wlan0WiFiIEEE 802.11 无线接口
rmnet_data0移动数据蜂窝数据接口
eth0以太网有线网口(平板/车机常见)
p2p0WiFi P2PWiFi Direct 接口
tun0VPNVPN 虚拟网络接口
rndis0USB 共享USB RNDIS 网络共享接口

5.2 接口生命周期

一个网络接口从出现到就绪经历:

接口创建 → 接口 UP → 配置 IP → 添加路由 → 网络就绪

关键:接口创建和 UP 由内核驱动触发(netd 被动接收 netlink 事件),配置 IP 和添加路由由 Framework 主动下发命令,网络就绪则由NetworkMonitor通过 ping 验证。这是一个"内核通知 → 用户态配置 → 验证确认"的协作流程。

各阶段对应的事件和操作:

阶段触发netd 处理Controller
接口创建内核驱动加载收到 RTM_NEWLINK 消息NetworkController
接口 UP驱动启动收到链路状态变化NetworkController
配置 IPDHCP / 静态配置Framework 下发命令NetworkController::setInterfaceConfig()
添加路由Framework 下发写入对应路由表RouteController
网络就绪路由 ping 通NetworkMonitor 验证

六、连接跟踪(conntrack)

netfilter 的 conntrack 模块会跟踪所有活动连接。这在网络共享(Tethering)中至关重要——NAT 需要根据连接跟踪表来决定如何转换返回的数据包。

# 查看当前连接跟踪表cat/proc/net/nf_conntrack# 典型条目:# ipv4 2 tcp 6 431999 ESTABLISHED src=192.168.43.5 dst=142.250.80.4# sport=45678 dport=443 src=10.0.0.1 dst=192.168.43.5 sport=443 dport=45678

关键:conntrack 表中的每条记录都包含原始方向和回复方向两个四元组——内核正是利用这个双向映射,在 NAT 场景下自动将返回数据包的目的地址从公网 IP 还原为内网 IP。

连接跟踪也用于-m state匹配,例如允许 ESTABLISHED 和 RELATED 的连接通过防火墙。


七、小结

本篇梳理了 Android 网络子系统在内核层的三个核心基础设施:

机制作用在 Android 中的关键使用场景
netfilter/iptables数据包过滤与修改防火墙、NAT 共享、DNS 拦截
策略路由 + fwmark多网络出口选择多网络并存、VPN 路由
连接跟踪连接状态维护NAT 转发、防火墙状态匹配

下一篇将深入 Native 层,拆解 netd 的启动流程和 CommandListener 架构——它是如何接收 Framework 层的命令,并通过这些内核机制完成网络操作的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/9 1:05:13

线段树 Beats 技巧在复杂区间问题中的实战解读

线段树 Beats 技巧简介 线段树 Beats 的核心思想&#xff1a;通过定制化的标记传递与剪枝策略&#xff0c;优化传统线段树在复杂区间操作中的性能。典型应用场景&#xff1a;区间最值操作&#xff08;如区间取 min/max&#xff09;、历史最值维护、复杂条件查询等。 线段树 B…

作者头像 李华
网站建设 2026/7/9 1:04:16

我和 Fable 5 聊了一晚上 AI,得出的结论大吃一惊

今天我跟ai连续聊了三个小时&#xff0c;围绕的重点就是ai未来到底会怎么样&#xff1f;这个念头我一直都有&#xff0c;但是没有找到合适的机会。直到最新的模型&#xff0c;Fable5出来了刚刚好有时间就跟他聊了一下。 下面就是我我比较感兴趣&#xff0c;围绕的几个地方&…

作者头像 李华
网站建设 2026/7/9 1:02:44

134.标准化 PLC 工程落地!扫描周期优化 + 防抖处理 + 状态机防死锁

摘要 可编程逻辑控制器(PLC)是工业自动化系统的核心控制单元。本文从工程实践角度出发,系统阐述PLC的硬件架构、扫描周期机制、I/O寻址原理,并通过一个完整的物料分拣控制系统案例,展示从需求分析、程序架构设计到结构化文本(ST)代码实现的全流程。文章提供可直接运行的…

作者头像 李华
网站建设 2026/7/9 0:55:51

BsMax插件:让3ds Max用户在Blender中无缝工作的终极解决方案

BsMax插件&#xff1a;让3ds Max用户在Blender中无缝工作的终极解决方案 【免费下载链接】BsMax BsMax Blender Addon (UI simulator/ Modeling/ Rigg & Animation/ Render Tools and ... 项目地址: https://gitcode.com/gh_mirrors/bs/BsMax 你是否厌倦了在不同3D软…

作者头像 李华
网站建设 2026/7/9 0:42:46

计算机毕业设计之民办高校二手物品交易网的设计与实现

本文论述了民办高校二手物品交易网的设计和实现&#xff0c;该网站从实际运用的角度出发&#xff0c;运用了计算机网站设计、数据库等相关知识&#xff0c;网络和Mysql数据库设计来实现的&#xff0c;网站主要包括用户注册、用户登录、浏览商品、搜索商品、查看商品并进行购买&…

作者头像 李华