用 nodejs 写了个 DNS 解析, UDP 转 DOT/TCP, 转 DOH

345 天前
 pagxir
11 月快要过去了,这个月研究了下 android 的 DOT,手写了个 DOT 实现,方便验证 android 的 DoT 行为

先说结论:
1 、DoT 是可以使用自签名证书的,并不是说非的需要一个正式的 HTTPS 证书。
2 、当选择自动模式的时候,代码实现上自动检测当前 DNS 服务器是否支持 TLS,并且 TLS 查询延迟不是比 UDP 差的多时候会自动选择 DOT,否则是 UDP 。所以自动模式下,如果当前的 DNS 服务器不支持 UDP ,只支持 TLS,手机也是能正常工作的。
3 、选择第三方 Dot 服务器,必须填域名,并且服务器的证书需要是正式签名的 HTTPS 证书。

Android 手机上的 Vpn 服务,默认需要 dns 跟地址都存在的才运行使用这个协议栈,所以理论上需要配置一个 ipv4 格式的地址一个 iPv4 格式的 DNS 服务器, 然后配置一个 ipv6 格式的地址加上一个 ipv6 格式的 DNS 服务器,才会双栈同时工作。当然了,也可以通过 VpnService.Builder.allowFamily 来关闭这个默认行为。

android DNS 解析器需要有缺省的路由才会解释对应协议栈的记录。所以手机连着只有 IPv4 的 Wifi ,然后建立 VpnService 是没有配置全局单播路由 2000::/3 那么,手机不会查询 AAAA 记录,也就是无法访问 IPv6 网络(即使你配置了部分的 ipv6 路由)。

所以, 如果 Vpn 的承载网络是 IPv4 单栈( wlan 或者蜂窝网络),需要在 VpnService.Builder 中添加 2000::/3 路由。

64:ff9b::/96 是默认的 NAT64 前缀,dns64.dns.google (2001:4860:4860::64,2001:4860:4860::6464) 支持返回 NAT64 的记录。不过它是没有 ipv6 记录情况下才会返回 NAT64 地址。所以这里实现,可以修改 pref 的配置,选择优先返回 NAT64 的地址。

这里实现,会有两个个上游 DNS 服务器,223.5.5.5 ,8.8.8.8 ,只返回 pref 高的记录
默认的 pref 顺序:

1 从 223.5.5.5 返回的并且是国内 IPv4 地址,最高优先级。
2 从 8.8.8.8 返回的 NAT64 记录。
3 从 8.8.8.8 返回的 ipv4 记录, 优先级跟 2 同。
4 从 8.8.8.8 返回的 IPv6 记录。
5 从 223.5.5.5 返回的 IPv6 记录。

所以只需要把 64:ff9b::/96 地址段选择正确的路由即可。不过就是需要本地网络开启双栈(不一定一定要全局 ipv6 地址)。

实现:
https://github.com/pagxir/dns-resolver-ng

测试地址 (因为 ECH facing server 只配置了 v6 网络,使用时需要 IPv6 网络,否则有问题):
https://test.855899.xyz/dns-query
1767 次点击
所在节点    DNS
1 条回复
pagxir
345 天前
在 linux 下,/etc/gai.conf 配置会影响 getaddrinfo 返回地址列表顺序。 里面 preference 是优先级顺序,数字越大优先级越高,label 是标签的意思,数字大小没有意义。顺序规则是先比较到达目标地址时选择的源的地址,如果源地址跟目标地址不在同一个 label 则优先级很低。
所以顺序就是,返回 preference 值高的并且源地址跟目标地址在同一个 label 的,然后是原地址跟目标地址在同一个 label 的其他记录,最后是原地址跟目标地址不在同一个 label 下的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/996265

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX