smartdns icon indicating copy to clipboard operation
smartdns copied to clipboard

如果上游只有doh时,dnsperf测试出现大量SERVFAIL(85%以上)

Open wangmice opened this issue 6 months ago • 18 comments

问题现象
简要描述问题出现的现象 如果上游只有doh时,dnsperf测试出现大量SERVFAIL(85%以上),感觉只有前面若干域名查询正常 运行环境

  1. 固件型号
    ubuntu 24.04

  2. 运营商

  3. smartdns来源以及版本 46.1

  4. 涉及的配置(注意去除个人相关信息)

重现步骤

  1. 上游DNS配置。
    server-https https://dns.google/dns-query -host-ip 8.8.8.8 -no-check-certificate -group cf -proxy xray
  2. 访问的域名。

信息收集

  1. 将/var/log/smrtdns.log日志作为附件上传(注意去除个人相关信息)。
  2. 如进程异常,请将coredump功能开启,上传coredump信息文件,同时上传配套的smartdns进程文件。
    在自定义界面,开启设置->自定义设置->生成coredump配置,重现问题后提交coredump文件 coredump文件在/tmp目录下

wangmice avatar May 17 '25 04:05 wangmice

smartdns连接doh上游时,有没有连接重用,超时之类的参数可以设置? [Status] Command line: dnsperf -d ./data/processed/domain-A-10000.txt -s 127.0.0.1 -p 1056 -m udp -c 100 -t 5 [Status] Sending queries (to 127.0.0.1:1056) [Status] Started at: Sat May 17 12:14:00 2025 [Status] Stopping after 1 run through file [Status] Testing complete (end of file)

Statistics:

Queries sent: 10000 Queries completed: 10000 (100.00%) Queries lost: 0 (0.00%)

Response codes: NOERROR 138 (1.38%), SERVFAIL 9844 (98.44%), NXDOMAIN 18 (0.18%) Average packet size: request 30, response 31 Run time (s): 228.156083 Queries per second: 43.829644

Average Latency (s): 2.266110 (min 0.000046, max 2.406129) Latency StdDev (s): 0.243429 大约从30个域名查询之后,全部为fail

wangmice avatar May 17 '25 04:05 wangmice

如果你的查询每秒超过100次,google将拒绝服务

PikuZheng avatar May 17 '25 04:05 PikuZheng

如果你的查询每秒超过100次,google将拒绝服务

但是为何udp正常?如果上游只设置为:server 8.8.8.8 错误率低于2%

wangmice avatar May 17 '25 04:05 wangmice

运营商劫持udp

PikuZheng avatar May 17 '25 04:05 PikuZheng

同样的配置,只更换了上游的测试结果: Statistics:

Queries sent: 10000 Queries completed: 10000 (100.00%) Queries lost: 0 (0.00%)

Response codes: NOERROR 8785 (87.85%), SERVFAIL 175 (1.75%), NXDOMAIN 1040 (10.40%) Average packet size: request 30, response 72 Run time (s): 17.943180 Queries per second: 557.314813

Average Latency (s): 0.161082 (min 0.000054, max 2.289929) Latency StdDev (s): 0.260508

wangmice avatar May 17 '25 04:05 wangmice

运营商劫持udp

通过透明代理翻的,不存在被劫持吧?

wangmice avatar May 17 '25 04:05 wangmice

在mosdns内测试了同样的doh上游,mosdns的测试结果正常。 Statistics:

Queries sent: 10000 Queries completed: 9994 (99.94%) Queries lost: 6 (0.06%)

Response codes: NOERROR 8785 (87.90%), SERVFAIL 162 (1.62%), NXDOMAIN 1047 (10.48%) Average packet size: request 30, response 98 Run time (s): 22.755007 Queries per second: 439.200041

Average Latency (s): 0.195032 (min 0.036653, max 4.697946) Latency StdDev (s): 0.352383

wangmice avatar May 17 '25 04:05 wangmice

能否分享一下 domain-A-10000.txt,我也测一测

PikuZheng avatar May 17 '25 05:05 PikuZheng

能否分享一下 domain-A-10000.txt,我也测一测

domain-A-10000.txt

能重现吗?

wangmice avatar May 17 '25 05:05 wangmice

localhost:~/smartdns# smartdns -c $(pwd)/smartdns.conf
localhost:~/smartdns# dnsperf -d $(pwd)/domain-A-10000.txt -s 127.0.0.1 -p 5353 -m udp -c 100 -t 5
DNS Performance Testing Tool
Version 2.14.0

[Status] Command line: dnsperf -d /root/smartdns/domain-A-10000.txt -s 127.0.0.1 -p 5353 -m udp -c 100 -t 5
[Status] Sending queries (to 127.0.0.1:5353)
[Status] Started at: Sat May 17 18:55:45 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         10000
  Queries completed:    10000 (100.00%)
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 51 (0.51%), SERVFAIL 9943 (99.43%), NXDOMAIN 6 (0.06%)
  Average packet size:  request 30, response 30
  Run time (s):         27.725040
  Queries per second:   360.684782

  Average Latency (s):  0.269307 (min 0.000138, max 2.449236)
  Latency StdDev (s):   0.684117

localhost:~/smartdns# kdig +https www.baidu.com @8.8.8.8
;; TLS session (TLS1.3)-(ECDHE-X25519)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
;; HTTP session (HTTP/2-POST)-(8.8.8.8/dns-query)-(status: 200)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 0
;; Flags: qr rd ra; QUERY: 1; ANSWER: 4; AUTHORITY: 0; ADDITIONAL: 1

;; EDNS PSEUDOSECTION:
;; Version: 0; flags: ; UDP size: 512 B; ext-rcode: NOERROR
;; PADDING: 337 B

;; QUESTION SECTION:
;; www.baidu.com.               IN      A

;; ANSWER SECTION:
www.baidu.com.          46      IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       3       IN      CNAME   www.wshifen.com.
www.wshifen.com.        261     IN      A       119.63.197.139
www.wshifen.com.        261     IN      A       119.63.197.151

;; Received 468 B
;; Time 2025-05-17 18:56:24 JST
;; From 8.8.8.8@443(HTTPS) in 47.1 ms
localhost:~/smartdns# kdig www.baidu.com @127.0.0.1:5353
;; ->>HEADER<<- opcode: QUERY; status: SERVFAIL; id: 42891
;; Flags: qr rd ra; QUERY: 1; ANSWER: 0; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;; www.baidu.com.               IN      A

;; Received 31 B
;; Time 2025-05-17 18:56:37 JST
;; From 127.0.0.1@5353(UDP) in 2195.5 ms

至此证实是smartdns的问题。等会儿我看看日志

PikuZheng avatar May 17 '25 10:05 PikuZheng

问了一deepseak:

高并发瓶颈​​ 单线程同步 SSL 发送可能成为性能瓶颈。参考 SmartDNS 文档,建议启用多线程模式(threads 2)。 缓冲区未限制大小,极端情况下可能导致内存耗尽(需结合 cache-size 参数控制)。 ​​TLS 握手开销​​ 未实现 TLS 会话复用(Session Resumption),每次连接需完整握手。可通过配置 tls-handshake-timeout 优化超时。 ​​HTTP/2 支持缺失​​ 当前代码基于 HTTP/1.1,而主流 DoH 服务已支持 HTTP/2。升级后可利用多路复用降低延迟。

http3.c **1. ​​流控与拥塞控制​​:**当前代码未显式实现 QUIC 的流级别流量控制(如 WINDOW_UPDATE 帧),可能在高并发场景下引发性能问题。 2. ​​会话复用优化​​:未使用 QUIC 的会话票据(Session Ticket)机制,每次连接需完整 TLS 握手,增加延迟。 3. ​​缓冲区管理​​:inpacket_data 固定大小为 DNS_IN_PACKSIZE,若上游响应过大(如 ECS 扩展数据),可能触发报文截断。

wangmice avatar May 17 '25 14:05 wangmice

测试了一下,223.5.5.5的情况下确实有这个问题。 但smartdns自己套自己的DOH查询测试是没有问题,性能也正常。 所以应该不是smartdns http处理出错的问题, 根本原因是应该是smartdns目前用了http1.1的协议,只要上游出现流控,就会导致后面的请求被上游服务器全部丢弃不响应。 后面看看增加http2的支持。 但C没有现成好用的http2库支持,这部分要手写,可能要很久。

目前的情况,家用应该是没有问题,并发300QPS的情况下,不会有问题。 所有建议是,如果有大量请求,改用DOT.

pymumu avatar May 17 '25 15:05 pymumu

​​nghttp2​​ 这个库可以用吗?

wangmice avatar May 17 '25 16:05 wangmice

如果缓存中的域名比较多,在预取的时候会触发这个问题吗

CallMeR avatar May 17 '25 18:05 CallMeR

只要你的上游不全是doh类型的话应该没问题

wangmice avatar May 18 '25 03:05 wangmice

测试了一下,223.5.5.5的情况下确实有这个问题。 但smartdns自己套自己的DOH查询测试是没有问题,性能也正常。 所以应该不是smartdns http处理出错的问题, 根本原因是应该是smartdns目前用了http1.1的协议,只要上游出现流控,就会导致后面的请求被上游服务器全部丢弃不响应。 后面看看增加http2的支持。 但C没有现成好用的http2库支持,这部分要手写,可能要很久。

目前的情况,家用应该是没有问题,并发300QPS的情况下,不会有问题。 所有建议是,如果有大量请求,改用DOT.

正确的,短时间大量请求触发了google的封锁。但是此时使用kdig测试https服务器又是通的。我猜是封了端口,改端口重连应该能缓解?

PikuZheng avatar May 18 '25 04:05 PikuZheng

如果缓存中的域名比较多,在预取的时候会触发这个问题吗

我的经验是预读也不会导致每秒100次以上

PikuZheng avatar May 18 '25 04:05 PikuZheng

如果你的查询每秒超过100次,google将拒绝服务

但是为何udp正常?如果上游只设置为:server 8.8.8.8 错误率低于2%

建议你不要用 Google 公共 DNS 来发送大量查询,除非你真的仔细阅读了他们的文档。

他们(在文档里)说得很清楚,Google 会强制执行 1500 QPS(每秒查询次数)的速率限制。这个限制适用于所有 IP,除非你是 ISP,并且明确向他们申请提高你 IP 的限制——但如果你没有一个“无论发生什么都不会改变/轮换的”静态专用公网 IP,(申请)获批的几率很低。

参考资料,这是他们的官方文档: https://developers.google.com/speed/public-dns/docs/isp

如果你想每秒推送超过 20000 个请求(当然,前提是你的硬件允许),可以试试 v.recipes DNS。vrcp 清楚地说明了他们实现了一种“单请求调速逻辑”(per-request pacing logic),所以从数学上讲,你不可能触发任何上游 DoH 提供商的速率限制(假设他们至少提供 1000 QPS 的限制)。

否则(如果你不用 vrcp),你就必须在应用层面自己实现这个(调速)逻辑,而这就需要你修改 App 的代码了。


这和你是用 DoH 还是 DoT 没关系。如果谷歌说了只允许 1500 QPS,那么用 DoH 还是 DoT 都无所谓,你不可能绕过这个限制。因为谷歌(很可能)是按 IP 地址来跟踪请求的,而不是按协议。

这并不是什么新鲜事,大多数公共 DNS 提供商都用同样的逻辑:就是追踪某个 IP 是否发送了过多请求,然后就(暂时)封掉它,直到那个 IP“冷静”下来。

这跟用 DoH 还是 DoT 毫无关系。除非 DNS 提供商明确表示“我们是按协议来限制请求的”,那时候你才能说“哦那我换成 DoT 就行了”(反之亦然)。😐

galpt avatar Nov 13 '25 08:11 galpt