DNS 解析器

DNS 解析器模块可保护用户免受 DNS 拦截和配置更新攻击,并改进了 DNS 解析的网络性能。此模块包含用于实现 DNS 桩解析器的代码,该解析器可将 www.google.com 等名称转换为 IP 地址(例如 2001:db8::1)。DNS 桩解析器支持 Java API 元素(如 InetAddress#getAllByNameNetwork#getAllByName)以及原生网络功能,且可发送和接收 DNS 查询以及缓存结果。

Android 10 中的变化

在搭载 Android 9 及更低版本的设备上,DNS 解析器代码分布在 Bionic 和 netd 上。DNS 查找操作集中在 netd 守护程序中,以便进行系统级缓存,而应用在 Bionic 中调用函数(例如 getaddrinfo)。查询会通过 UNIX 套接字发送到 /dev/socket/dnsproxyd,再到 netd 守护程序,该守护程序会解析请求并再次调用 getaddrinfo 以发出 DNS 查找请求,然后它会缓存结果以供其他应用使用。DNS 解析器实现主要包含在 bionic/libc/dns/ 中,部分包含在 system/netd/server/dns 中。

Android 10 将 DNS 解析器代码移至 system/netd/resolv,,将其转换为 C++,然后对代码进行翻新和重构。由于应用兼容性方面的原因,Bionic 中的代码继续存在,但系统不会再对其进行调用。以下源文件路径受到重构的影响:

  • bionic/libc/dns
  • system/netd/client
  • system/netd/server/dns
  • system/netd/server/DnsProxyListener
  • system/netd/server/ResolverController
  • system/netd/resolv

格式和依赖项

DNS 解析器模块(“com.android.resolv”)以 APEX 文件的形式提供,并由 netd 动态链接;但是 netd 不是依赖项,因为模块会直接提供本地套接字 /dev/socket/dnsproxyd。解析器配置的 Binder 端点已从 netd 移至解析器,这意味着,系统服务可以直接调用解析器模块,无需通过 netd

DNS 解析器模块依赖于 libc (Bionic) 并静态链接其依赖项;不需要使用其他库。

mDNS .local 解析

自 2021 年 11 月起,Android 解析器支持 mDNS .local 解析,后者可在 RFC 6762 中实现“5.1 单次模式多播 DNS 查询”,以便不加辨识地将标准 DNS 查询发送至 224.0.0.251:5353 或 [FF02::FB]:5353。只需使用以 *.local 结尾的主机名调用 getaddrinfo() 即可透明地支持 mDNS 解析。

mDNS .local 解析增强了 getaddrinfo() 获取地址的现有功能。如果设备支持 mDNS .local 解析,那么 getaddrinfo() API 会将 mDNS 查询发送到 224.0.0.251:5353 或 [FF02::FB]:5353,并返回本地地址。如果设备不支持 mDNS .local 解析,那么 getaddrinfo() API 方法会向 DNS 服务器发送 DNS 查询。

代码位于 AOSP 的 packages/modules/DnsResolver 中。用户可以保留其当前的 mDNS 设计来获取地址,或改用 getaddrinfo()。此功能的行为类似于发送到 mDNS 多播地址的常规 DNS 查询。此功能对系统运行状况没有影响。

用户可以使用 adb shell ping6 HOSTNAME.local 命令,其中 HOSTNAME 是 LAN 中目标设备的主机名,例如 adb shell ping6 ipad.local

VPN 和移动网络连接不在 .local 解析范围内。