网络堆栈配置工具

Android 操作系统包含标准的 Linux 网络实用程序,例如 ifconfigipip6tables。这些实用程序位于系统映像上,可以配置整个 Linux 网络堆栈。在运行 Android 7.x 及更低版本的设备上,允许供应商代码直接调用这些二进制文件,这会带来以下问题:

  • 由于网络实用程序在系统映像中更新,因此它们不提供稳定的实现。
  • 网络实用程序的范围非常广泛,以至于难以在保证可预测行为的同时改进系统映像。

在运行 Android 8.0 及更高版本的设备上,供应商分区保持不变,而系统分区会收到更新。为了实现这一点,Android 8.0 提供了定义稳定、版本化接口的功能,同时还使用 SELinux 限制来将供应商映像和系统映像的相互依赖性保持在已知良好的集合中。

供应商可以使用平台提供的网络配置实用程序来配置 Linux 网络堆栈,但这些实用程序尚不包含 HIDL 接口封装容器。为了定义此类接口,Android 8.0 包含 netutils-wrapper-1.0 工具。

Netutils 封装容器

netutils 封装容器实用程序提供 Linux 网络堆栈配置的子集,该子集不受系统分区更新的影响。Android 8.0 包含版本 1.0 的封装容器,您可以使用与封装的实用程序相同的参数,这些实用程序安装在系统分区中的 /system/bin 中,如下所示:

u:object_r:system_file:s0           /system/bin/ip-wrapper-1.0 -> netutils-wrapper-1.0
u:object_r:system_file:s0           /system/bin/ip6tables-wrapper-1.0 -> netutils-wrapper-1.0
u:object_r:system_file:s0           /system/bin/iptables-wrapper-1.0 -> netutils-wrapper-1.0
u:object_r:system_file:s0           /system/bin/ndc-wrapper-1.0 -> netutils-wrapper-1.0
u:object_r:netutils_wrapper_exec:s0 /system/bin/netutils-wrapper-1.0
u:object_r:system_file:s0           /system/bin/tc-wrapper-1.0 -> netutils-wrapper-1.0

符号链接显示由 netutils 封装容器封装的网络实用程序,其中包括:

  • ip
  • iptables
  • ip6tables
  • ndc
  • tc

要在 Android 8.0 及更高版本中使用这些实用程序,供应商实现必须遵守以下规则:

  • 供应商进程不得直接执行 /system/bin/netutils-wrapper-1.0;尝试这样做会导致错误。
  • 所有由 netutils-wrapper-1.0 封装的实用程序都必须使用其符号链接启动。例如,将之前执行此操作的供应商代码(/system/bin/ip <FOO> <BAR>)更改为 /system/bin/ip-wrapper-1.0 <FOO> <BAR>
  • 在平台 SELinux 策略中,禁止在没有域转换的情况下执行封装容器。此规则不得更改,并在Android 兼容性测试套件 (CTS)中针对此规则进行了测试。
  • 在平台 SELinux 策略中,还禁止从供应商进程直接执行实用程序(例如,/system/bin/ip <FOO> <BAR>)。此规则不得更改,并在 CTS 中针对此规则进行了测试。
  • 任何需要启动封装容器的供应商域(进程)都必须在 SELinux 策略中添加以下域转换规则:domain_auto_trans(VENDOR-DOMAIN-NAME, netutils_wrapper_exec, netutils_wrapper)

Netutils 封装容器过滤器

封装的实用程序可用于配置 Linux 网络堆栈的几乎任何方面。但是,为了确保可以维护稳定的接口并允许更新系统分区,仅允许某些命令行参数组合;其他命令将被拒绝。

供应商接口和链

封装容器具有供应商接口的概念。这些接口通常由供应商代码管理,例如蜂窝数据接口。通常,其他类型的接口(例如 Wi-Fi)由 HAL 和框架管理。封装容器通过名称(使用正则表达式)识别供应商接口,并允许供应商代码对其执行许多操作。目前,供应商接口包括:

  • 名称以“oem”结尾后跟数字的接口,例如 oem0r_oem1234
  • 当前 SOC 和 OEM 实现使用的接口,例如 rmnet_data[0-9]

通常由框架管理的接口的名称(例如 wlan0)永远不是供应商接口。

封装容器具有类似的供应商链概念。这些用于 iptables 命令中,并且也通过名称识别。目前,供应商链包括:

  • oem_ 开头。
  • 当前 SOC 和 OEM 实现使用的链,例如,以 nm_qcom_ 开头的链。

允许的命令

下面列出了当前允许的命令。限制通过对执行的命令行上的一组正则表达式来实现。有关详情,请参阅 system/netd/netutils_wrappers/NetUtilsWrapper-1.0.cpp

ip

ip 命令用于配置 IP 地址、路由、IPsec 加密和许多其他网络参数。封装容器允许以下命令:

  • 从供应商管理的接口添加和删除 IP 地址。
  • 配置 IPsec 加密。

iptables 和 ip6tables

iptablesip6tables 命令用于配置防火墙、数据包修改、NAT 和其他每数据包处理。封装容器允许以下命令:

  • 添加和删除供应商链。
  • 在任何链中添加和删除规则,这些规则引用进入 (-i) 或离开 (-o) 供应商接口的数据包。
  • 从任何其他链中的任何点跳转到供应商链。

ndc

ndc 用于与 netd 守护进程通信,该守护进程在 Android 上执行大多数网络配置。封装容器允许以下命令:

  • 创建和销毁 OEM 网络 (oemXX)。
  • 将供应商管理的接口添加到 OEM 网络。
  • 向 OEM 网络添加路由。
  • 全局以及在供应商接口上启用或停用 IP 转发。

tc

tc 命令用于在供应商接口上配置流量队列和整形。