Conversation
https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.1 mapdns回复报文中不存在 Additional RRs,根据rfc定义,ARCOUNT可以是0
相比之前的实现,如何做到维持更长时间的ip -> domain的映射了? 另外,现在的实现对于同一个域名的多次解析请求,是不是就会重复占用多条记录? |
|
在windows11上系统默认的缓存直接把解析记录ttl调整成一天,安卓手机我就不太清楚了。 如果规范的dns缓存客户端,就会在域名映射的环形缓冲区出现多个记录。 |
那就是说原先的实现相对更容易造成 192.168.1.2 -> github.com 的映射被释放,是什么原因? |
|
windows和安卓的dns缓存策略就像个黑盒子,只能用这种笨方法防止不规范的缓存。 |
|
就像CDN一样 一个ip可能对应几十上百个域名,他们通过”SSL SNI“ ”ALPN“之类的扩展。就能通过一个ip访问很多网站 |
|
|
主线现在的实现,只要缓存记录的总数没有超过cache-size,就不会释放映射记录,已经建立的映射关系就不会改变。如果超过了cache-size,最不常被访问(根据记录中的Fake IP统计的)的那条记录会被释放。 理论上这样的场景会出现错误映射,一个域名被解析并分配了一个Fake IP,之后很长时间没有再访问过这个Fake IP,使得这条记录很冷。然后随着系统的运行,解析的域名越来越多,超过了cache-size,之前那条映射记录由于最冷被释放了,系统DNS缓存没有失效,最后这个Fake IP又被访问,出现错误的映射关系。 我觉得问题的关键是不能在系统DNS缓存没超时前出现回收,这个PR的环形记录也是一样会回收的,而且还存在同域名重复记录(有的应用会绕过带缓存的DNS自己直接发DNS请求的)。应该在现有的基础上调整更大的cache-size来避免问题。 |
是的,我也是想避免系统发出ip包时域名映射失效。但是系统的客户端缓存策略就是个黑盒。根本找不到多少能参考的资料。 |
|
嗯。当前的PR+前置dnsmasq去重叠加后的效果,与主线的实现对比,如果没达到cache-size,映射都是唯一且稳定的;如果都超过了cache-size,都会回收旧记录。看起来都差不多,不能缓解问题吧? |
|
稍等一会,我突然想到一个事。我之前在调试v2.14.1的时候,mapdsn出现过50ms+的延迟。我去找一份域名列表。编译以下主线的软件和改过的对比以下mapdns响应速度 |
好。性能上来说,主线的实现解析记录是动态内存分配(后端有个带缓存的分配器);domain -> ip的查找(因为要去重)是O(log n);ip -> domain的查找是O(1)。 |
|
在i7-7700k上测试了默认mapdns配置,按顺序解析( |
|
平常心,重构和性能对比本来就是不断试错的过程,这次的结论同样很有价值。非常感谢你的投入和探索,期待你后续更多的贡献 |

在windows 11上使用hev-socks5-tunnel搭建的透明网关时,发现windows 11上系统的dnscache缓存策略不符合rfc规范
ipconfig /displaydns。windows 11默认dns缓存延长到86400秒。mapdns对于这种不规范的缓存客户端,需要建立ttl持续时间更长的[ip->domain]映射方法。
以下是这个提交的实现原理:
假设
等效于
192.168.1.0/241.已知
hev-socks5-tunnel只需要[ipv4-> domain]单向映射。2.mapdns可用
ip 192.168.1.0 ~ 192.168.0.255,,广播地址 192.168.1.255网络地址 192.168.1.0,实际可用地址192.168.1.1 ~ 192.168.1.2543.为了方便管理 每个映射分配一个
char[256],使用位运算 NOT~netmask申请一块char[~netmask][256]大小的内存作为环形缓冲区。处理流程:
1.收到 “github.com”的DNS A请求,分配环形缓冲区首个地址
192.168.1.1,将DNS请求数据包的域名写入char[1][256]2.tun设备收到
192.168.1.1的tcp链接,(uint32_t)(192.168.1.1 - 192.168.1.0) = index3.取地址运算
&(char[index][0])得到映射域名的 char[256]的缓冲区地址,完成ip->域名的映射。缺点:
1.为了方便管理 每个缓冲区都是rfc1035规定的域名最长值,需要耗费更多的内存 。(每个域名映射256字节)
2.每个dns请求会分配一个映射块(配合前置缓存服务器,这甚至是个优点)
[mapdns <- dnsmasq chche]优点:
1.避免内存管理的开销,环形缓冲区初始化时申请一次大块内存,直到程序运行结束释放。不存在mapdns运行产生的内存碎片。
2.快速映射,一些简单的指针运算就能直接得到映射到对应域名 O(1)
3.更长的TTL,在环形缓冲区对应的char[256]没被覆盖之前,ip映射的域名始终有效。避免不规范的缓存客户端导致的映射失败。
要点:
1.
cache-size用于限制最大的char[256]块数量假设
cache-size: 10000 network: 192.168.0.0/16~mask =65536 但会被限制为 10000char[10000][256]大约需要 2.44MiB内存2.增加
hev_mapped_dns_cache_ttl函数,需要作者加入yaml配置选项,可以控制前置缓存的ttl 例如dnsmasq因为不太熟练,如果代码中有换行 代码对齐之类的格式问题,麻烦作者合并代码后帮忙修改一下。