Comments (48)
这个 10.0.23.172 是 chinadns-ng 所在机器的还是其他机器的?
$ fgrep 'query [safebrowsing.googleapis.com]' chinadns-ng.log | awk '{print $(NF-1)}' | sort | uniq
10.0.23.172#34065
10.0.23.172#49736
10.0.23.172#54354
10.0.23.172#55054
10.0.23.172#56825
10.0.23.172#57499
10.0.23.172#60149
10.0.23.172#62897
10.0.23.172#64578
from chinadns-ng.
我本地复现不出来。
想看下你的 iptables 规则,有点怀疑是 iptables 规则导致死循环了。
for t in raw mangle nat filter; do
echo "========= $t ==========="
iptables -t $t -S
done
from chinadns-ng.
如果能稳定复现,麻烦安装下 strace 工具,然后将 strace 捕获的系统调用日志发我下,我看看咋回事。
strace -s1024 -ttv chinadns-ng 命令行参数 2>&1 | tee -a chinadns-strace.log
from chinadns-ng.
这次关闭了ss-rules以排除干扰
这个版本的OpenWRT似乎只有nftables了,附上nft list table inet fw4
nft.log
和strace日志
chinadns-strace.log.zip
10.0.23.*是内网其他主机
from chinadns-ng.
看了strace日志,并没发现 chinadns-ng 本身有什么异常,这些请求全部来自同一客户机:
$ fgrep recvfrom chinadns-strace.log | head -n1
10:58:26.619475 recvfrom(4, "\236\275\1\0\0\1\0\0\0\0\0\0\7clients\1l\6google\3com\0\0\1\0\1", 1472, 0, {sa_family=AF_INET, sin_port=htons(63862), sin_addr=inet_addr("10.0.23.172")}, [28 => 16]) = 38
# 请求都是来自 .172 主机(发起ssh连接的那台主机),chinadns-ng 运行在 .1 主机
$ fgrep recvfrom chinadns-strace.log | \grep -Po 'inet_addr\(.+?\)' | sort | uniq
inet_addr("10.0.23.172")
# 发送dns查询的src-port是这些,前面的数字是重复的次数(可以理解为客户机使用此端口发送的dns查询数量)
$ fgrep recvfrom chinadns-strace.log | \grep -Po 'htons\(.+?\)' | sort | uniq -c
1 htons(12069)
1 htons(12116)
1 htons(14069)
1 htons(14219)
1 htons(15264)
1 htons(1736)
1 htons(17771)
1 htons(18246)
1 htons(20167)
1 htons(20346)
1 htons(20638)
1 htons(2226)
1 htons(22497)
1 htons(23366)
1 htons(23497)
1 htons(24228)
1 htons(24230)
1 htons(24875)
1 htons(26797)
1 htons(26878)
1 htons(27314)
1 htons(28454)
1 htons(31382)
1 htons(33537)
1 htons(33805)
1 htons(34994)
1 htons(35877)
1 htons(36719)
1 htons(36767)
1 htons(37122)
1 htons(37412)
1 htons(38234)
1 htons(40174)
2649 htons(40824)
1 htons(40961)
1 htons(41149)
1 htons(41215)
2649 htons(43460)
1 htons(43513)
1 htons(46053)
21 htons(49283)
2 htons(49350)
2 htons(49407)
32 htons(49997)
1 htons(50821)
1 htons(50891)
1 htons(51274)
1 htons(51278)
6 htons(51442)
5 htons(51615)
2 htons(51977)
2 htons(52193)
1 htons(52716)
3 htons(52936)
1 htons(53446)
1 htons(53503)
4 htons(53929)
8 htons(54023)
1 htons(54060)
1 htons(54148)
2 htons(54234)
1 htons(54340)
5 htons(54448)
1 htons(54564)
2 htons(54729)
1 htons(54782)
1 htons(54831)
5 htons(54874)
1 htons(55027)
5 htons(55194)
1 htons(55581)
1 htons(56025)
5 htons(56136)
1 htons(56195)
2 htons(56333)
19 htons(56527)
4 htons(56604)
3 htons(56686)
5 htons(56847)
1 htons(56861)
1 htons(56998)
5 htons(57050)
2 htons(57246)
5 htons(57345)
5 htons(57557)
3 htons(57811)
3 htons(57915)
1 htons(57919)
3 htons(58066)
1 htons(58407)
2 htons(58725)
5 htons(58808)
1 htons(59159)
2 htons(59329)
3 htons(59406)
4 htons(59449)
2 htons(59500)
20 htons(59604)
5 htons(60112)
1 htons(60166)
3 htons(60354)
1 htons(60428)
1 htons(60748)
5 htons(60824)
1 htons(60907)
13 htons(60910)
5 htons(61120)
6 htons(61222)
4 htons(61269)
3 htons(61592)
1 htons(61664)
21 htons(61669)
1 htons(61705)
2 htons(61971)
5 htons(62006)
7 htons(62559)
2 htons(62890)
1 htons(62969)
1 htons(63062)
2 htons(63070)
1 htons(63131)
10 htons(63171)
1 htons(63276)
5 htons(63330)
1 htons(63442)
4 htons(63777)
6 htons(63858)
2 htons(63862)
4 htons(63867)
4 htons(63887)
4 htons(64016)
5 htons(64048)
1 htons(64165)
4 htons(64349)
1 htons(64411)
8 htons(64471)
4 htons(64542)
5 htons(64651)
1 htons(64838)
1 htons(64860)
4 htons(64866)
2 htons(64943)
2 htons(64979)
1 htons(65449)
1 htons(8972)
1 htons(9238)
看起来比较可疑的就是这两个端口,发送的 dns 查询数量有 2649 次:
2649 htons(40824)
2649 htons(43460)
from chinadns-ng.
10.0.23.172是一台ikuai路由器,下面有上百个设备,大量请求是合理的,那么同一端口等于是子网内某一台主机吧?
日志中create new socket, old socket is used for %d这条在不停出现且数字在增长,正常情况应该是每60s一个?
from chinadns-ng.
create new socket, old socket is used for %d
这个log没问题,这个log后面还有一条:
there are 1886 unfinished queries, continue to use the old
意思是,当前还有未完成的 query(还没收到 response),所以继续用之前的 socket。
事实上,我搜了 log,upstream socket 并没有 close,一直都是最开始创建的那两个:
$ fgrep epoll chinadns-strace.log | fgrep -v wait
10:58:26.276121 epoll_create1(0) = 5
10:58:26.276226 epoll_ctl(5, EPOLL_CTL_ADD, 4, {events=EPOLLIN, data={u32=4, u64=4}}) = 0
10:58:26.620591 epoll_ctl(5, EPOLL_CTL_ADD, 6, {events=EPOLLIN, data={u32=0, u64=0}}) = 0
10:58:26.621059 epoll_ctl(5, EPOLL_CTL_ADD, 7, {events=EPOLLIN, data={u32=2, u64=2}}) = 0
from chinadns-ng.
我仔细分析了 chinadns-ng 收到的 query msg,以及 forward 给上游的 query msg。没发现什么异常。
异常的情况是,上游从未返回数据:
$ grep -o 'handle_[\w_]++' chinadns-strace.log | sort | uniq -c
34434 handle_local_packet
7704 handle_timeout_event
这说明所有请求最终都会超时。
我认为你应该检查下为什么上游从来没有 response 过。
from chinadns-ng.
另外,你在开头说 你使用了 dns2tcp 作为上游,但我看了你发的所有 log(包括最开始那次),都是用的 8.8.8.8。
虽然这和当前的问题没啥关系。。
from chinadns-ng.
另外,我统计了一下 chinadns-ng 在运行期间收到的 query 数量:
[10:58:26] -> [10:59:50] 差不多 1 分 30 秒,共 5739 个查询,大概每秒 68 个请求。
感觉不是死循环,如果是死循环,那么 query 频率肯定不会这么低。
$ wc -l all*
5739 all_forward_data.txt
5739 all_req_data.txt
11478 total
from chinadns-ng.
综上所述,这里面最大的问题是:国内和国外上游从未响应 chinadns-ng 的请求。
如果你设置了 iptables/nftables 规则,将流量重定向给 ss-redir,建议你看下 ss-redir 的日志。
from chinadns-ng.
为了排除干扰,strace这次没有用dns2tcp和ss-redir。
而且就算是--trust-dns=114.114.114.114也出现了同样的问题……
from chinadns-ng.
日志中create new socket, old socket is used for %d这条在不停出现且数字在增长,正常情况应该是每60s一个?
这里我需要说明下,从程序逻辑上来说,这条log的出现是完全正常的,不是异常情况。
这个逻辑是从 2023.05.08 版本开始引入的。
目的是避免长时间使用同一个端口(socket)与 dns upstream 通信,具体你可以看下 #125
所以给 upstream socket 设置了一个 life time,目前是 60s。
也就是说每 60s 会换一个新的 socket(因此 src 端口号通常会变化),用来与 upstream 通信。
当然,更换新 socket 的前提是,当前没有 未完成的dns查询(否则这些未完成的查询必定失败,因为再也没有机会从 upstream 收到他们的 response 了)。
如果检测到有 未完成的dns查询,那么 socket 更替逻辑 将延后,这就是你经常看到 there are 1886 unfinished queries, continue to use the old
打印的原因。
因为你这里的 upstream 一直不响应,因此堆积的未完成 query 越来越多,所以更替逻辑一直在延后。
正常来说,一个 dns 查询会很快收到 response(通常也就是几十毫秒),所以就算出现延后处理,也就是维持个几秒钟。不会出现你这种极限情况。
from chinadns-ng.
为了排除干扰,strace这次没有用dns2tcp和ss-redir。
而且就算是--trust-dns=114.114.114.114也出现了同样的问题……
那你要看下你的网络环境了,你在 chinadns-ng 所在机器,用 dig 测下:
dig @114.114.114.114 baidu.com
dig @114.114.114.114 github.com
dig @114.114.114.114 google.com
看下是否能正常响应。
from chinadns-ng.
总之,你要解决 上游不响应 这个核心问题。
from chinadns-ng.
为了排除干扰,strace这次没有用dns2tcp和ss-redir。
而且就算是--trust-dns=114.114.114.114也出现了同样的问题……那你要看下你的网络环境了,你在 chinadns-ng 所在机器,用 dig 测下:
dig @114.114.114.114 baidu.com dig @114.114.114.114 github.com dig @114.114.114.114 google.com看下是否能正常响应。
baidu.com正常,github和google超时。
这种情况的处理是不向用户返回任何结果?哪怕是china-dns是有结果的?
而且超时也有个等待过程吧,为什么会触发像死循环一样的大量请求
在我后续测试中已经不能在开启程序1分钟准时复现了,但10分钟内还是会出现的。
from chinadns-ng.
另外关于 chinadns-ng 几个使用上的建议:
- 指定大陆域名列表,让这些域名的查询只转发给 china 上游(单纯转发query和response,没有额外逻辑):
-m chnlist.txt
- 指定污染域名列表,让这些域名的查询只转发给 trust 上游(单纯转发query和response,没有额外逻辑):
-g gfwlist.txt
- 对于其他不在列表的域名,需要导入 chnroute.ipset、chnroute6.ipset,用于 ip 判定,只允许使用 china 上游返回的是国内ip的情况,如果不是,则一律使用 trust 上游的结果。
from chinadns-ng.
你目前的 chinadns-ng 参数,很容易出问题,因为全都是 tag:none 域名,tag:none 域名总是先考虑 china 上游的结果,当 china 上游的结果不合适时(也就是 A/AAAA 查询,ip不是大陆ip),才会采纳 trust 上游的结果。
from chinadns-ng.
你目前的 chinadns-ng 参数,很容易出问题,因为全都是 tag:none 域名,tag:none 域名总是先考虑 china 上游的结果,当 china 上游的结果不合适时(也就是 A/AAAA 查询,ip不是大陆ip),才会采纳 trust 上游的结果。
为了定位问题,这些功能都暂时没有开。正常使用时是会使用域名和ip过滤的。
from chinadns-ng.
那当然不行,就算是定位问题,也是要按照常规使用模式来的。
from chinadns-ng.
baidu.com正常,github和google超时。
这种情况的处理是不向用户返回任何结果?哪怕是china-dns是有结果的?
首先,从你给的 strace 日志来看,你的所有上游(无论是 china 还是 trust)都没有进行任何响应(不是一两个请求不响应,是所有,这1分半内的所有请求!),那肯定就是超时,毫无悬念。程序总不能凭空给你捏造一个 response 吧。
from chinadns-ng.
为什么会触发像死循环一样的大量请求
之前的分析都已经说了,这些请求都是来自其他机器的,而且你说有几百个客户端在下面,按照平均每秒 68 个查询的频率来看,也不是死循环。。
from chinadns-ng.
总之问题不在于请求(而且请求频率也不是你说的死循环这种情况),问题在于所有上游都没返回数据。
from chinadns-ng.
另外,这是之前关于去掉 抢答模式 的一些讨论,有谈到上游 timeout 的一些话题
from chinadns-ng.
我觉得这个帖子的标题存在误导。
上午看到这个 issue 后,我一直在看 epoll 相关的东西,然而并未发现什么可疑的地方会导致你说的死循环。
另外也怀疑是否 forward 给 upstream 的时候发生了什么神奇的操作,导致 forward 给 chinadns-ng 的监听端口了,这是我能想到的第二种会导致死循环的情况。然而也不是这种情况(而且理论上上不可能有这种情况,除非是不正确的 iptables/nftables 规则导致的)。
问题核心还是 上游没有响应的问题。
from chinadns-ng.
开了域名和ip列表似乎持久了一些……然并卵。
公平模式能理解,处理是正确的,可是为什么china上游也不给我返回结果呢……这个联通dns已经十数年没有坏过了吧
from chinadns-ng.
我觉得这个帖子的标题存在误导。
上午看到这个 issue 后,我一直在看 epoll 相关的东西,然而并未发现什么可疑的地方会导致你说的死循环。
另外也怀疑是否 forward 给 upstream 的时候发生了什么神奇的操作,导致 forward 给 chinadns-ng 的监听端口了,这是我能想到的第二种会导致死循环的情况。然而也不是这种情况(而且理论上上不可能有这种情况,除非是不正确的 iptables/nftables 规则导致的)。
问题核心还是 上游没有响应的问题。
说得对,似乎是什么导致了上游不仅仅是timeout……更像是reset
from chinadns-ng.
在 chinadns-ng 正常运行过程中,如果发现上游不响应(看日志能知道),那么立即进行 dig 测试(在 chinadns-ng 所在机器):
- dig @chinadns-ng的国内上游ip 发生超时的域名(其他域名也可以试下)
- dig @chinadns-ng的可信上游ip 发生超时的域名(其他域名也可以试下)
如果 dig 这边总是能够正常 query/response,但是 chinadns-ng 不正常,请告诉我。
from chinadns-ng.
我有点怀疑和 #125 类似,可能对于你这边的上游 DNS 来说,socket life time 60 秒还是太长了,导致 upstream 拒绝给你响应(因为你这几十秒内,一直使用相同的 src-ip && src-port 请求,恰好你的网络环境下,DNS 查询频率也比较高,服务器可能认为你在 DDOS 攻击?)
from chinadns-ng.
我有点怀疑和 #125 类似,可能对于你这边的上游 DNS 来说,socket life time 60 秒还是太长了,导致 upstream 拒绝给你响应(因为你这几十秒内,一直使用相同的 src-ip && src-port 请求,恰好你的网络环境下,DNS 查询频率也比较高,服务器可能认为你在 DDOS 攻击?)
要验证这个情况,有个很简单的方法,你修改下源码,重新编译。
Line 27 in 66426e2
将 60 改为 1 看下。
改为 0 也可以
from chinadns-ng.
如果确实是这个原因,那么后面我会给一个命令行参数,用于调整 life time,而不是写死。
from chinadns-ng.
musl报错了所以没有使用。
SOCK_LIFETIME改为1后似乎更容易崩溃了
from chinadns-ng.
什么报错?
崩溃?进程掉了?麻烦说清楚。
from chinadns-ng.
什么报错?
崩溃?进程掉了?麻烦说清楚。
指的是CPU占用满
最近尝试了不同方法试图修复:
- 在前面加了dnsmasq转发,之后没有再出现cpu占用满的情况,但变成了所有dns查询均无法响应,客户端表现为浏览器报错dns无响应
- 去掉了--noip-as-chnip,似乎排除了问题,不再有无响应的情况发生,由于联通dns返回结果不稳定(间断地墙),可复现的域名可能有:api.blocknative.com,a.nel.cloudflare.com,wandb.ai,g.live.com,api.wallet.coinbase.com。这些域名的特点是CNAME域名,并且不在gfwlist和chnlist里表现为直接查询上游(dns2tcp 8.8.8.8)正常,但chinadns-ng拒绝返回结果。这个表现在我使用的旧版(v1.0-beta.25)中没有出现。log里出现了之前没有的报错:
2023-11-20 13:45:35 I [main.c:330 handle_remote_packet] reply [g.live.com] from 202.96.69.38 (2802), result: filter 2023-11-20 13:45:35 I [main.c:332 handle_remote_packet] reply [g.live.com] from <previous-trustdns> (2802), result: accept 2023-11-20 13:45:35 W [ipset.c:607 test_res_ipset] error when querying ip: (22) Invalid argument
from chinadns-ng.
你说的那个报错,确定ipset导入成功了?你这是查询chnroute的报错。
from chinadns-ng.
nft list table inet global
有内容,而且只有少数域名才有这个报错,需要的话我可以把ipset上传
from chinadns-ng.
命令行参数如何指定的?nft需要特殊格式,family@table@set
from chinadns-ng.
用的是--ipset-name4 chnroute
from chinadns-ng.
参数格式错了,具体看readme。--help也有说格式。
chinadns-ng 的启动日志里面,也会打印当前使用的是 ipset 还是 nftset。
from chinadns-ng.
-4, --ipset-name4 <set4> ip test for tag:none, default: chnroute
-6, --ipset-name6 <set6> ip test for tag:none, default: chnroute6
if setname contains @, then use nft-set
format: family_name@table_name@set_name
from chinadns-ng.
明白了,nft的set name是inet@global@chnroute而不是chnroute对吧
from chinadns-ng.
是的,如果用的是默认nftset数据文件。
from chinadns-ng.
如果你的china-dns有超时的情况,建议同时指定两个china-dns,一个是你的联通dns,一个是稳定的不会超时的dns,比如119.29.29.29、223.5.5.5、114.114.114.114
from chinadns-ng.
另外,如果可以,建议给 china-dns 上游配置 DoH(chinadns-ng 2.0 准备内置 DoH 上游支持,目前可以借助 dnsproxy 工具来实现),上 DoH 不容易被干扰,也就不会出现你说的超时的情况。
from chinadns-ng.
--noip-as-chnip
选项我建议你先看下 README 中的相关说明,先了解作用,再决定是否要用。我个人不认为必须用这个选项。
from chinadns-ng.
--noip-as-chnip
选项我建议你先看下 README 中的相关说明,先了解作用,再决定是否要用。我个人不认为必须用这个选项。
这个开了很久了(beta.25),当时解决了什么问题已经记不清了……
from chinadns-ng.
现在的版本与b25版本有一些改变,建议重新过一下readme。
from chinadns-ng.
readme也对很多东西做了原理上的分析,对排查问题绝对是有帮助的。当你深刻理解运行原理和每个参数后,才能用好。
from chinadns-ng.
Related Issues (20)
- 建议可在上游地址前加上 udp:// 来强制使用 UDP DNS HOT 8
- 请教该下哪个版本合适? HOT 3
- 添加 ip 到 ipset/nftset 时,支持指定元素级别的 timeout 参数
- 关于新版本的使用方法 HOT 20
- `--no-ipv6` 修改: 不过滤、过滤所有、按域名tag过滤、按ip测试结果过滤 HOT 5
- 新版本(2024.03.27)的 udp 似乎有问题 HOT 5
- [ipset.c:606 test_res_ipset] error when querying ip: (2) No such file or directory HOT 2
- [增强] 支持 `udp://` 上游 HOT 37
- tag 的说明和功能的例子是混淆了? HOT 2
- --add-tagchn-ip 选项可否设置黑名单 HOT 17
- 对于不支持tcp查询的上游,请带上`udp://`限定 HOT 12
- 是否个例:域名层级问题 HOT 3
- 使用 chinadns-ng 替代 dnsmasq 时,需要注意的事项 HOT 81
- 环境有问题,DNS解析存在“污染” HOT 60
- 24.4.13版本用不了 ,是改变什么吗 HOT 3
- 增加-Dwolfssl编译不过去 HOT 7
- wolfssl 在某些平台上无法正确校验 SSL 证书 HOT 10
- tag有可能支持geosite吗 HOT 1
- 路由器上使用chinadns,一直日志里显示网络不可达 HOT 4
- 请问一下能否支持通过tcp/socks5访问上游 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from chinadns-ng.