自定义Node.js DoH服务器处理自定义TLD域名时客户端无法解析响应的问题解决
解决自定义DoH服务器转发响应后客户端NXDOMAIN问题
你的问题核心在于DNS响应的域名和ID与客户端原始请求不匹配,导致浏览器无法关联响应与自己的请求,从而返回DNS_PROBE_FINISHED_NXDOMAIN。下面是具体的分析和解决方案:
问题根源拆解
你当前拿到的Google DoH响应是针对bafybeie5nqv6kd3qnfjupgvz34woh3oksc3iau6abmyajn7qvtf6d2ho34.ipfs.dweb.link的,但客户端实际请求的是mydomain.customtld。DNS协议有两个核心要求:
- 响应的
id必须与请求的id完全一致,否则客户端会认为这是无关响应 - 响应中
questions和answers的name字段必须匹配客户端请求的域名,否则浏览器会判定该域名未被正确解析
具体修复步骤
你需要在转发响应前,修改返回的DNS数据包,让它与客户端的原始请求对齐:
1. 提取客户端原始请求的关键信息
首先要从客户端的DoH请求中解析出id、请求的域名和记录类型(A/AAAA等)。假设你已经通过dohjs拿到了客户端的请求对象(比如clientDnsRequest):
// 从客户端请求中提取核心信息 const clientRequestId = clientDnsRequest.id; const clientRequestedDomain = clientDnsRequest.questions[0].name; const clientRequestType = clientDnsRequest.questions[0].type;
2. 解析目标IPFS链接并修改响应
拿到Google DoH的响应后,修改id、questions和answers中的域名:
const doh = require('dohjs'); const resolver = new doh.DohResolver('https://dns.google/dns-query'); // 根据客户端请求的类型解析IPFS链接 let dnsAnswer = await resolver.query( `bafybeie5nqv6kd3qnfjupgvz34woh3oksc3iau6abmyajn7qvtf6d2ho34.ipfs.dweb.link`, clientRequestType ); // 1. 对齐响应ID与客户端请求ID dnsAnswer.id = clientRequestId; // 2. 修改question的域名以匹配客户端请求 dnsAnswer.questions[0].name = clientRequestedDomain; // 3. 修改所有answer的域名 dnsAnswer.answers.forEach(answer => { answer.name = clientRequestedDomain; }); // 此时修改后的响应就可以正确编码发送给客户端了
3. 额外注意事项
- 如果客户端请求的是AAAA(IPv6)记录,一定要确保你调用
resolver.query时传入的类型是'AAAA',而不是固定的'A' - 保持响应中的其他字段(比如TTL、data、flags)不变,这些字段是Google DoH返回的有效信息,不需要修改
这样修改后,浏览器收到的响应会完全匹配它的请求,就能正确解析mydomain.customtld到目标IP地址了。
内容的提问来源于stack exchange,提问作者ajaleksa
相关产品推荐
相关产品推荐

