smartdns icon indicating copy to clipboard operation
smartdns copied to clipboard

新增一组选项,单独控制返回给 DNS 客户端的 ttl

Open asbai opened this issue 2 years ago • 15 comments

需求应用场景

  1. 大前提:很多服务使用 geo-DNS 来优化访问性能,因此最好以实际访问的出口节点 IP 完成 DNS 查询。
  2. 拓扑:SmartDNS 所在节点需要在新加坡、韩国、北美等不同线路间动态切换,为确保 geo-DNS 优化, SmartDNS 向上游 DNS 查询时均以当前线路对应的海外节点身份发起。此外,每次发生线路切换后都会自动重启 SmartDNS 并清空其缓存。
  3. 但是线路发生切换后,SmartDNS 的下游客户端中缓存的 DNS 解析结果未必会过期,导致线路切换后客户端仍长时间访问对上个线路友好的 IP。
  4. 现有的 rr-ttl 系列选项在修改了 SmartDNS 返回最终客户端响应中的 ttl 时(详见对 _dns_server_get_conf_ttl方法的各处引用),也一并影响了其自身缓存的有效性。导致调小这些设置会引发 SmartDNS 不必要的密集发起上游查询请求。

建议的方案 专门定义一套只影响返回最终客户端应答中 ttl 的选项,但这组选项不会影响 SmartDNS 内存或磁盘缓存时长。

asbai avatar Apr 01 '22 02:04 asbai

最简 POC (共 5 行代码):

  1. 打开 dns_server.c。
  2. 新增一行代码:#define _dns_server_get_return_ttl(ttl) (ttl >= 10 ? 10 : ttl)
  3. _dns_server_process_answer_A_dns_server_process_answer_AAAA 中的 _dns_server_get_conf_ttl 调用替换为 _dns_server_get_return_ttl (影响 4 行代码)。

此 POC 在不影响 SmartDNS 缓存 ttl 的前提下,将返回给下游客户端的 ttl 最大值固定为 10 秒。实际产品中应当考虑提供与 rr-ttl 系列对应的三个选项。

asbai avatar Apr 01 '22 03:04 asbai

抱歉,刚才抓包看了下,好像上面的 POC 不足以保证返回的 ttl-max。我只是快速过了一下代码,感觉要是连 _dns_server_get_answer 里的 _dns_server_get_conf_ttl 都替换的话,应该会影响到 SmartDNS 的缓存 ttl 吧?

asbai avatar Apr 01 '22 04:04 asbai

我也希望能够单独控制返回给客户端的ttl,希望在openwrt上能够使用大ttl让dns结果缓存,然后返回客户端的ttl可以比较小,让客户端不至于出现一些dns缓存问题。强烈建议可以考虑下这个功能,还有也可以考虑一下增加对DoQ的支持。

fangjia052 avatar Apr 26 '22 14:04 fangjia052

有没有检查过现在smartdns答复下游查询的ttl究竟是多少?我在没有修改默认配置的情况下,下游获取到的ttl大多在10秒左右

PikuZheng avatar Apr 27 '22 11:04 PikuZheng

有没有检查过现在smartdns答复下游查询的ttl究竟是多少?我在没有修改默认配置的情况下,下游获取到的ttl大多在10秒左右

我测试过,我设定的ttl是10,然后答复客户端有时候是10,有时候是二十几

fangjia052 avatar Apr 28 '22 08:04 fangjia052

总之用的时间长了,总感觉差了点什么。好长时间都没有增加什么新功能了,比如增加对DoQ的支持,支持更加复杂的分流(其实也不需要多复杂,就想把chinadns替换掉,经常出问题)等等。还有一些问题是使用的时候发现的,speed-check-mode tcp:443,tcp:80会使用tcp80测试而不是tcp443,当设置成speed-check-mode tcp:80,tcp:443就恢复到tcp443测试。还有前面说到的设定的ttl值与客户端查询到的ttl值不一致的情况。还有域名预先获取功能似乎会无视分组,会直接使用默认DNS组去获取。

fangjia052 avatar Apr 28 '22 08:04 fangjia052

可以取用all-best-ip代码分支测试。参数为rr-ttl-reply-max,表示返回给客户端的最大ttl值,不影响cache的时间。

@fangjia052 dns服务,最重要是稳定,没有什么新花样。 如果是软件BUG,可以提交issue,并提交相关的复现过程和日志。

pymumu avatar Apr 30 '22 00:04 pymumu

可以取用all-best-ip代码分支测试。参数为rr-ttl-reply-max,表示返回给客户端的最大ttl值,不影响cache的时间。

收到,多谢!

asbai avatar May 01 '22 16:05 asbai

可以取用all-best-ip代码分支测试。参数为rr-ttl-reply-max,表示返回给客户端的最大ttl值,不影响cache的时间。

可以了,但是 rr-ttl-reply-max 好像会随时间递减。例如:

  1. 设置 rr-ttl-reply-max 10,重启 smartdns。
  2. dig google.com @1.1.1.1 实际返回 TTL 是 300。
  3. 一秒后 dig google.com,此时 TTL 返回 10,此时 google.com 条目在 smartdns cache 内的实际 TTL(actual_ttl)还剩 299s。
  4. 再一秒后执行 dig google.com,此时 TTL 返回 9,而此时 actual_ttl 还剩 298s。

希望第四步仍然返回 10,而非 9。只有当 actual_ttl 小于 10 时,才应返回小于 10 的 TLL。 换句话说,smartdns 返回给客户端的 TTL 应该取 min(dns_conf_rr_ttl_rely_max, actual_ttl)

asbai avatar May 01 '22 20:05 asbai

rr-ttl-reply-max表示的是返回最大值,是会递减的,就是这样设计的。并不是返回一个固定值。 这个递减是会循环的,不是减少到0,就一直返回0。是会再次变成最大值。

pymumu avatar May 02 '22 01:05 pymumu

rr-ttl-reply-max表示的是返回最大值,是会递减的,就是这样设计的。并不是返回一个固定值。 这个递减是会循环的,不是减少到0,就一直返回0。是会再次变成最大值。

多谢回复 :-)

这样递减的好处是什么呢?相比较而言,是不是我们之前提起的 “取 min(dns_conf_rr_ttl_rely_max, actual_ttl)” 更合理一些?毕竟记录的实际 TTL 还剩 298 呢,此时返回 10 感觉比 返回 9 更合理一些,希望考虑。

asbai avatar May 02 '22 01:05 asbai

更新了。

pymumu avatar May 02 '22 15:05 pymumu

更新了。

好使!期待合入 Master :-D

asbai avatar May 02 '22 19:05 asbai

另外 dns_conf_rr_ttl_rely_max 貌似有个 typo:dns_conf_rr_ttl_reply_max

asbai avatar May 02 '22 19:05 asbai

在此版本中发现一个问题:当设置了 serve-expired no 时,每次客户端向 SmartDNS 发起查询都会引发 SmartDNS 向上级 DNS 查询。即:serve-expired no 完全禁用了 SmartDNS 的本地缓存功能(即使缓存的条目 TTL 尚未归零)。

UPDATE: 发现问题了:https://github.com/pymumu/smartdns/issues/922

asbai avatar May 03 '22 00:05 asbai

这样递减的好处是什么呢?相比较而言,是不是我们之前提起的 “取 min(dns_conf_rr_ttl_rely_max, actual_ttl)” 更合理一些?毕竟记录的实际 TTL 还剩 298 呢,此时返回 10 感觉比 返回 9 更合理一些,希望考虑。

上述问题在最新的 Release 42 版上又重现了。

asbai avatar May 09 '23 11:05 asbai

修正了。

pymumu avatar May 09 '23 15:05 pymumu