由于手头的一些设备不太方便甚至不能配置DoH,所以准备在家中的局域网里自建一个DNS代理,将DNS请求转为DoH进行查询,在保障隐私的同时也有着良好的兼容性和可维护性。

在习惯性地开始动手造轮子的同时还是调研了下,dnscrypt-proxy作为比较成熟的软件已经能满足我的需求,且配置方便灵活,资源占用也不高,所以干脆放弃造轮子,直接用现成的。

安装dnscrypt-proxy

虽然Ubuntu仓库提供了dnscrypt-proxy,但毫不意外地进行了“定制”。为了省去debug的功夫,建议按照官方wiki的Linux安装指南手动安装一遍。文档写得还是蛮详细的,这里就不赘述安装流程了,我照着步骤一遍过了。

配置dnscrypt-proxy

其实官方wiki里写得也比较详细了,这里我提几个我格外留意的配置项吧

DNS服务器

我注释掉了所有sources,只使用手动配置的static服务器。一方面是访问官方的sources列表存在困难,而第三方提供的列表很难完全信任;另一方面是家庭使用情况下,通常也只用的上那么几个固定的DNS服务器,手动配置一下反而更方便维护和排错。

我使用的是Cloudflare和NextDNS的DoH服务,手动生成了复数个使用不同IP的备选项,当无法正确解析DoH服务器的IP时至少有个兜底。通过这个工具可以计算所需的形如sdns://的DNS stamp,比如我就在默认的1.1.1.1之外给Cloudflare DoH加了cloudflare-dns.com的备选项。

dnscrypt-proxy会定期测试服务器延迟,默认采用的是lb_strategy = 'p2',从最快的2个服务器中随机选择。也是出于这一考虑我就没在dnscrypt-proxy里配置阿里云DNS作为fallback——毕竟近水楼台,响应肯定永远是最快的。

速度优化

官方wiki里提到了三种速度优化:拦截IPv6、DNS缓存和加密套件。

拦截IPv6(block_ipv6 = true)说实话我没测试出来很显著的性能提升,虽然家里现在没弄IPv6,但考虑到之后可能会用上,加之我还是希望给局域网里的所有设备完整的DNS响应,所以最后还是没配置拦截。

默认的缓存策略会在内存中缓存最近4K条查询,TTL看起来也相对合理。家用场景下更高的cache_size似乎作用不大,可惜用不完给虚拟机配的1GB内存了。

加密套件目前也相对无所谓,我用的x86虚拟机承载DNS服务,不像在树莓派或者路由器的ARM处理器上要省着用计算资源。所以按默认配置以免之后还要查兼容性问题。

Cloaking

简单来说可以类比hosts文件,我给几台局域网下的关键服务器配置了便于访问的域名,省的给每台新机器一个个改hosts。

其它

虽然dnscrypt-proxy提供了丰富的blocking、filtering、forwarding等等功能,但是我把它们大多禁用了。我需要的只是一个安全可靠的DNS服务器,它目前做好域名解析的工作就够了;至于拦截广告和阻止访问某些网站等等,这些工作我觉得可以也应该由设备/应用和它们的使用者自己决定。

应用自建DNS

各个运行桌面/服务器OS的机器都好说,配置自建的DNS服务地址作为首选DNS,备选填上阿里云DNS以防整活失败全家断网。

各个“智能”设备则只能靠路由器DHCP分发DNS了,在路由器配置里同样配置自建DNS首选,然后重启路由器让所有设备重新联网。某些设备可能比较固执,而且我也不知道这些黑箱里到底是怎么执行网络相关逻辑的,总之还是把几个“最需要它们能正常运行”的设备本身也重启了一下。

目前能测试到的DNS请求都走自建DNS了,缓存生效的时间内能立即响应,需要通过DoH请求的域名会慢一点,但实际使用起来没啥感觉。总之我已经在没有通知任何人的情况下把家里路由器上DNS改了,如果这几天家里人没反馈网络有问题的话那就当一切安好了。