V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CharonVIII
V2EX  ›  宽带症候群

相同 DNS 服务器用 dig 能解析出 IP 而 nslookup 不能

  •  
  •   CharonVIII · 250 天前 · 2314 次点击
    这是一个创建于 250 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近我在访问一个论坛:www.ai2moe.org 的时候发现访问异常,排查后发现是 DNS 解析错误。

    我平常用的 223.5.5.5 和 119.29.29.29 的 UDP DNS ,跑在 openclash 上。 然后我用把 openclash 关掉,在软路由上用 dig 和 nslookup 进行测试,测试结果如下:

    1. 运营商 DNS 在 nslookup 和 dig 下都正常
    2. dig 下,223.5.5.5 正常
    3. nslookup 下,114DNS 正常而 223.5.5.5 异常(重点!!)

    详细结果如下四图: 223.5.5.5 测试 dig 正常而 nslookup 异常: https://img.chkaja.com/b98e8e559e1bfa8f.png

    114DNS 测试 nslookup 正常: https://img.chkaja.com/ae9cab6d9b411af7.png

    114DNS 测试 dig 正常: https://img.chkaja.com/9a0b19830aae75b9.png

    运营商 dig 正常: https://img.chkaja.com/44e034a3964b1f20.png

    运营商 DNS nslookup 正常: https://img.chkaja.com/42ac2f962d94a18e.png

    并且根据此网站结果可得 223.5.5.5 解析是没有污染的: https://dig.ping.pe/www.ai2moe.org:A:223.5.5.5

    而且运营商 DNS 解析正常说明这个问题也不是 DNS 劫持,不然直接用运营商 DNS 也无法访问才对。

    然后我又测试了下换成阿里的 DoH 就又可以正常解析了。。玄学问题了。

    求教坛友们这可能是出在什么问题上?实在排查不出来了。

    第 1 条附言  ·  250 天前
    首先感谢 @Tianao @jinqzzz 提供的排错思路。
    先放结论:分析下来结论是 223.5.5.5 没问题,我电脑自己不管是用运营商 DNS 还是 223.5.5.5 访问网站都没问题,所以问题只能出在过了 openclash 内核以后就寄了。分析下来这可能更像是 openclash 内核的问题,我去反馈下这个问题。

    1. 开始的时候怀疑是 223.5.5.5 由于 UDP 查询返回的 A 记录过多,超过了 512 字节,于是 223.5.5.5 用 TCP 再进行查询,在这过程中 DNS 服务器不能正常响应(返回了 TCP RST 包),从而导致用 223.5.5.5 查询 nslookup 失败。
    114DNS 和运营商 DNS 自己丢弃了部分 A 记录让返回的结果小于 512 字节,所以 nslookup 没问题。
    而 223.5.5.5 dig 查询成功的原因是 dig 采用 EDNS0 ,允许 4096 字节长的结果返回,所以 dig @223.5.5.5 www.ai2moe.org 的结果正常。

    2. 后来又经过测试在关闭 openclash 的情况下在 openwrt 上用命令 dig +tcp @223.5.5.5 -p 53 www.ai2moe.org ,返回结果正常,说明 openwrt 上是可以对 223.5.5.5 进行 TCP 的 UDP 查询,得出结论:223.5.5.5 的 TCP 查询是没问题的。

    3. 再测试 PC 的 DNS 手动设置为 223.5.5.5 后测试访问 www.ai2moe.org ,结果竟然可以正常访问。而打开 openclash ( openclash 只设置一个 223.5.5.5 的 Nameserver )就无法正常访问 www.ai2moe.org
    第 2 条附言  ·  248 天前
    更新:已向 OpenClash 仓库维护者 V 大反馈此问题: https://github.com/vernesong/OpenClash/issues/3811

    V 大表示是内核的问题,于是我又向 meta 内核发了 issue ,目前等待回复中: https://github.com/MetaCubeX/mihomo/issues/1117
    第 3 条附言  ·  243 天前
    3/24 更新:
    在 meta 内核 alpha-d56a439 已经修复此问题。

    https://github.com/MetaCubeX/mihomo/issues/1117#issuecomment-2016511149
    14 条回复    2024-04-10 19:42:38 +08:00
    Tianao
        1
    Tianao  
       250 天前   ❤️ 12
    权威解析给这个 CNAME 配的 A 记录太多了,dig 在请求的时候携带了 UDP payload size (比如我的 macOS 的默认是 4096), 所以 223.5.5.5 会直接使用 UDP 返回这个八百多字节的递归解析结果; nslookup 默认没有在请求里携带 UDP payload size 信息,223.5.5.5 默认按 512 对待,返回了 Truncated flag 置位,让客户端去用 TCP 再请求一次。

    至于楼主的 nslookup 为什么没有成功通过 TCP 解析,就要检查 nslookup 的实现、DNS 客户端的配置和 TCP 的联通性了(比如 telnet 223.5.5.5 53 )。我的 macOS 的 nslookup 是会在这样输出之后正确显示最终的 A 记录的:
    nslookup www.ai2moe.org 223.5.5.5
    ;; Truncated, retrying in TCP mode.

    至于为什么阿里的 DoH 没问题,因为 DoH 和使用 53 端口的 DNS 是两个完全不同的协议,不存在这个默认最大 512 字节的限制。

    至于为什么 119.29.29.29 和 114.114.114.114 和运营商 DNS 使用相同的 nslookup 和相同的 DNS 协议也没问题,因为它们直接无视了来自 DNS 客户端的 DNS 请求中携带的 UDP payload size, 偷偷把超长递归解析结果裁剪到不超过 512 字节(在本例中,是通过随机丢弃 A 记录的方式)通过 UDP 直接返回了。
    CharonVIII
        2
    CharonVIII  
    OP
       250 天前
    @Tianao 大佬太厉害了,分析非常详细,感觉给我开辟了新大陆!

    我刚才测试了下 telnet 223.5.5.5 53 ,显示空白页面,应该代表对 223.5.5.5 的 53 端口的 TCP 连接是通畅的。
    然而我用电脑又试了下 nslookup www.ai2moe.org 223.5.5.5 ,结果显示:
    ————————————————————————
    nslookup www.ai2moe.org 223.5.5.5
    服务器: public1.alidns.com
    Address: 223.5.5.5

    DNS request timed out.
    timeout was 2 seconds.
    *** 请求 public1.alidns.com 超时
    ————————————————————————
    还是感觉原因不明啊。

    其实这种事情也真是我上了这么多年网第一次遇到,太异常了。照理说 A 记录太多的网站肯定不止这一家...
    Tianao
        3
    Tianao  
       250 天前   ❤️ 1
    @CharonVIII #2 我测试下来,是 Windows 上的 nslookup 实现在通过 UDP 收到 Truncated 置位的应答、转而使用 TCP 并完成 TCP 的 3-way 握手后,会紧接着(也就是在这个 TCP 连接的第 4 个包)发送一个带有 PSH 置位的、仅有 2 bytes 的 TCP payload 的 TCP segment, 我不知道这个 2-byte 载荷的意义是什么(但猜测是用作一个什么出于性能或可用性目的的什么前导?),然后紧接着就收到了来自 223.5.5.5 的 TCP RST (我也不知道 223.5.5.5 为什么要 reset, 但是我猜测是 223.5.5.5 收到了这个不明所以的 TCP 分段,出于节省资源开销/防攻击的目的主动 reset 掉了这个 TCP 连接),然而按照 Windows nslookup 的预期(这一「预期」我使用了其他使用 Windows nslookup 可以正常解析的 DNS 服务器进行了验证),这第 5 个包本应是来自服务端的正常 ACK, 然后 nslookup 再紧接着发送可以和第 4 个包进行 TCP segment reassemble 从而组成一个完整 DNS 请求的 TCP 分段,但是此时 TCP 连接已经被 223.5.5.5 给 reset 掉了。

    目前的判断:Windows 的 nslookup 实现和 223.5.5.5 的某些策略性表现在 TCP 解析时存在兼容性问题。

    目前的建议:在 Windows 上,在 PowerShell 中使用 Resolve-DnsName 能够获得比 nslookup 更接近 Windows DNS 客户端真实表现的测试结果。换言之,在 Windows 上,仅是 nslookup 失败不代表浏览器等真实用户访问行为调用的 DNS 解析也会失败。

    「照理说 A 记录太多的网站肯定不止这一家...」
    对于一般 web 服务的 GSLB, 国内一般都是地理+运营商分区解析,每个分区最终的 A/AAAA 记录真的远没这么多;对于国际化服务,虽然会使用 anycast, 但是 ADNS 会控制每次返回给 recursive DNS 的权威结果数量,也不会一次性返回好几十个 anycast 地址的 A 记录。
    CharonVIII
        4
    CharonVIII  
    OP
       250 天前
    @Tianao 感谢分析,我这边还没测试过直接在 windows 上设置 DNS 为 223.5.5.5 能否正常访问网站(估计不行),但是我测试过由跑在 openwrt 上的 openclash 来代为用 223.5.5.5 解析 DNS 的话是解析结果错误的。

    看你的原因分析感觉非常有道理,确实如果是这个原因的话就说得通了。那么最好的办法要么在阿里、腾讯 DNS 之外再加个 114DNS 或者运营商 DNS ,要么就用阿里和腾讯的加密 DNS 。

    我现在的解决方案就是 openclash 用阿里和腾讯的 DoT 来规避 UDP DNS 的 payload size limit 的问题(当然用 DoH 也行),目前情绪稳定。
    jinqzzz
        5
    jinqzzz  
       250 天前
    关于为什么没有自动 fallback 到 tcp ,我指出两点可能的存在的线索,仅供楼主参考:
    首先,看楼主是在 openwrt 上边测试,openclash 可能劫持了你发向 wan 的 dns 请求
    其次,clash dns 服务器是不支持 tcp mode 的
    jinqzzz
        6
    jinqzzz  
       250 天前   ❤️ 1
    dig 命令可以测试 dns 服务器是否支持 tcp ,比如 dig +tcp @127.0.0.1 -p 1053 www.baidu.com
    465456
        7
    465456  
       250 天前
    同时使用运营商 DNS ,和 DNS-over-QUIC 就没问题
    CharonVIII
        8
    CharonVIII  
    OP
       250 天前
    @jinqzzz 我测试都是关掉 openclash 再测试的。
    刚才测试了下关闭 openclash 的情况下在 openwrt 上用命令 dig +tcp @223.5.5.5 -p 53 www.ai2moe.org ,返回结果正常,说明 openwrt 上是可以进行 TCP 的 UDP 查询的,得出结论:223.5.5.5 的 TCP 查询是没问题的。

    我又把 PC 的 DNS 手动设置为 223.5.5.5 后测试访问 www.ai2moe.org ,结果竟然可以正常访问。而打开 openclash ( openclash 只设置一个 223.5.5.5 的 Nameserver )就无法正常访问 www.ai2moe.org
    所以就是说 223.5.5.5 没问题,我电脑自己不管是用运营商 DNS 还是 223.5.5.5 访问网站都没问题,问题就出在过了 openclash 内核以后就寄了。。分析下来这可能更像是 openclash 内核的问题,我去反馈下看看。

    谢谢各位大佬们的思路!
    fredcc
        9
    fredcc  
       249 天前
    不知道 op 用的哪个版本的 clash 内核,也不知道 dns 分流配置怎么写的,测试 meta alpha-g44d8a14 解析正常
    CharonVIII
        10
    CharonVIII  
    OP
       249 天前
    @fredcc 我用最新的 alpha-gb3db113 版本测试下来依然是无返回结果,如图:

    https://img.chkaja.com/4353234effd209ab.png
    465456
        11
    465456  
       248 天前
    @CharonVIII 为啥一定要用 udp ,用 DoH/DoT 不香吗?
    johnjiang85
        12
    johnjiang85  
       225 天前
    这个还需要看 dns 服务端对 tcp 请求的兼容性问题,不是所有版本的 windows 的 nslookup 都有这个,只是部分版本的 nslookup 有这个问题。

    当客户端发起 tcp 请求的时候,tcp 的 dns 请求是由 2 个字节的长度包+实际的 dns 请求组成的,部分较旧版本的 nslookup 会把两个部分分开发送,而 dig 和较新版本的 nslookup 会将两部分一起发送。

    当 dns 服务端对 tcp 的 dns 请求数据不进行分段接收数据的支持处理的话,比如只支持一次性收到 2 字节的长度包,和完整的后续 dns 请求包,那么这些老版本的 nslookup 分 2 次发送的数据包,在 dns 服务端收到的数据和前 2 字节的数据包长度不匹配,就会校验失败,然后关闭 tcp 连接。

    如果需要兼容此类客户端,需要在 dns 服务端进行修改,支持 tcp dns 请求的时候,没有一次性收到完整数据的场景,即需要自己对客户端的 tcp 连接和已收到部分数据做额外的管理,会复杂一些。
    johnjiang85
        13
    johnjiang85  
       225 天前
    可以使用老版本 nslookup 或 nc 来模拟分段发送 dns 请求
    johnjiang85
        14
    johnjiang85  
       225 天前
    { echo -n -e "\x00\x2b";sleep 1; echo -n -e "\x69\x6f\x01\x20\x00\x01\x00\x00\x00\x00\x00\x01\x0a\x6c\x6f\x76\x65\x6c\x79\x70\x69\x6e\x67\x03\x63\x6f\x6d\x00\x00\x01\x00\x01\x00\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00"; } | nc 1.12.0.1 53

    nc 模拟在同一个 tcp 连接中分段发送 DNS 请求的示例,此处是向 1.12.0.1 发送 tcp dns 请求域名 lovelyping.com 的 A 记录
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5332 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 07:11 · PVG 15:11 · LAX 23:11 · JFK 02:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.