深入解析DNS over HTTPS(DoH)的技术困境与替代方案

本文探讨了DNS over HTTPS(DoH)协议的技术问题,包括隐私风险、协议栈冲突和中心化控制,并介绍了DNS over TLS(DoT)作为加密替代方案,详细说明了如何配置Stubby和Bind实现DNS流量加密。

DNS over HTTPS(DoH)的混乱局面

作者:Joff Thyer //

本周一早上醒来时,我觉得是时候重新审视一下我网络中的域名服务(DNS)配置了。(这个想法也源于在2021年内华达州里诺市Wild West Hackin’ Fest活动中观看许多讨论并与Paul Vixie进行交流。)

背景是,我从不认为应该依赖本地互联网服务提供商(ISP)的DNS基础设施。无意冒犯,但我一直认为ISP基础设施是靠胶带和铁丝勉强维持的,而我始终是个“自己动手”的人。

换句话说:“嘿,伙计们,只需给我一个光纤到以太网的交接,将我的静态地址路由给我,传递我的数据包,剩下的交给我。”我很幸运找到了一家正是这样做的ISP,甚至表示如果我拥有地址块,他们会传递边界网关协议(BGP)表给我。哇,这简直是天籁之音!

毫不奇怪,过去我曾自己管理过拥有数千个端点的大型网络,而我的家庭网络也管理得井井有条。没错,我自己处理路由、网络地址转换(NAT)、动态主机配置协议(DHCP)和DNS服务。我的网络非常可靠——当然,前提是上游能传递这些数据包!

现在,来谈谈令人不安的话题。我们生活在监控资本主义的时代,作为全球互联网社区,我们实际上让各种公司通过挖掘我们不断产生的数据残渣而逍遥法外。

DNS是互联网的基础。其设计本质上是高度分布式的!在自己的网络中运行自己的DNS服务器,并指示DHCP告诉网络端点你的DNS是正确且真实地将域名转换为IP地址的地方,这是100%可接受且鼓励的。不幸的是,对于家庭网络,大多数人没有技能自己操作,而是依赖小型办公室/家庭办公室(SOHO)路由器供应商的产品,其中许多产品设计廉价且高度脆弱;唉,这个话题改天再谈。

当DNS遇到监控资本主义时,糟糕的事情就会发生。当任何明文协议可在网络上读取并被挖掘以获取金钱回报时,你的隐私正在被侵犯,你正在成为巨额收入的来源。

如果你运行自己的DNS服务器,有一个小小的补救措施,那就是缓存的概念。你的本地DNS服务器代表客户端存根解析器(端点)发出的任何DNS请求都会有一个称为生存时间(TTL)的缓存值,你的DNS服务器必须遵守这一点。你的DNS服务器会“记住”一个请求的答案,持续TTL指定的秒数。

如果你运行自己的DNS服务器,并且不将所有请求转发给另一个DNS提供商(如8.8.8.8),你的DNS服务器必须请求根名称服务器来帮助解析请求。下图基本上展示了你的本地DNS服务器在查找www.whitehouse.gov时的行为。

查找www.whitehouse.gov DNS A记录时的DNS服务器操作

问题是什么?作为安全专业人员,我们喜欢良好的加密,但说实话,DNS并不太令人满意,因为它没有加密。

DNSSEC呢?抱歉,DNSSEC无法帮助我们,因为它的目标是确保答案的准确性/防止欺骗,这有助于解决缓存中毒问题,但DNSSEC不保护传输中的数据。

好吧,事实证明,各种浏览器供应商提出了有史以来最糟糕的想法之一。这个想法是通过HTTPS传输DNS请求。https://datatracker.ietf.org/doc/html/rfc8484

现在,你可能会有不良反应。我的意思是,HTTPS是加密的,对吧?是的,没错,它是加密的,但还记得上面的监控资本主义评论吗?

想想看……如果你的DNS流量被发送到浏览器供应商的基础设施,你的数据更容易受到监控。事实上,发生的是对你的数据的显著控制和权力的集中!此外,通过这样做,高度分布式架构的极端操作稳定性突然集中到了少数人手中。开放标准和自由互联网的所有原则正在被少数数据挖掘者颠覆。

从协议的角度来看,我们还在交叉流。HTTP =“超文本传输协议”,而DNS不是超文本!因此,我们面临垂直协议栈单浏览器供应商锁定的情况。这是我们想要的吗?这是正确的解决方案吗?

在文章的这一点上,我感到非常矛盾。我的意思是,可靠的加密难道不是好事吗?作为安全专业人员,我们支持经过充分测试、研究、强大的加密,但我个人无法支持这一点,同时我的隐私被如此彻底地侵犯。

我更矛盾的是,我没有真正的保证我的本地ISP也没有挖掘我的加密数据。我们从这里转向哪里?

还有一种DNS加密形式已经存在了一段时间,称为DNS over Transport Layer Security(DoT)。https://datatracker.ietf.org/doc/html/rfc7858

简而言之,DoT至少试图做正确的事情,在TCP端口853上有一个适当的监听TCP服务,并以符合适当开放标准协议的方式使用传输层安全性(TLS)。挑战在于DoT确实是一个新协议,我们如何/能否指示我们的客户端端点存根解析器正确使用这个协议?当然,我们可以回到我们的老朋友DHCP,并有一些选项;然后,我们必须希望所有操作系统供应商在DNS存根解析器代码中做正确的事情,根据需要实现TLS支持。

好吧,毫不奇怪,“正确的解决方案”并不总是胜过“简单的解决方案”。DoT需要很多改变,而人们不喜欢改变,尤其是对于像电力一样无处不在的期望水平的东西。

(《辛普森一家》是迪士尼的财产)

但等一下——我在数据监控这个话题上并不完全公平。

以下是按域名列出的DNS over HTTPS提供商示例列表(讽刺,是吧?)。其中许多声称通过操作弹性和过滤恶意软件/间谍软件域/广告提供增值服务。

好吧,看完这个列表,可以公平地说,上述大多数都有相当强大的隐私声明(有一个明显的例外)。

因此,我最强烈的反对意见在于协议栈的违反,以及个别浏览器无视你的本地网络配置,承担客户端存根解析器进程的功能。这对于绝对需要对其网络协议行使安全控制的大型企业网络操作来说远不可接受。

碰巧的是,上述许多DoH提供商也支持DoT。所以,回到我周一早上重新检查网络中DNS的目标,我花了一点时间集中思考我的舒适水平。归结如下:

  • 我绝对100%相信任何能够的人应该运行自己的内部DNS服务器。
  • 我希望继续能够诊断和查看我自己网络中发生的DNS流量。
  • 运行我自己的内部DNS服务器使我能够配置和运行我自己的域过滤服务,这我已经实施了多年。如果你不像我一样自己操作,考虑Pi-Hole项目。https://github.com/pi-hole
  • 我对ISP将监控资本主义视为收入来源的想法感到不安,因此很可能在检查我的DNS流量。
  • 我对破坏DNS原始形式的分布式稳定美感到矛盾,但强大的加密从来不是坏主意。

我决定继续运行我自己的DNS服务器,但使用DoT加密从该服务器到Quad9的流量。阅读后,感觉Quad9在所有提供商中拥有最好的利益和意图。与此相结合,我将通过iptables规则主动阻止到任何这些公共提供商的DoH,该规则使用动态IP集更新,我可以根据需要更改。是的,这意味着直接阻止到一组特定IP地址的TCP端口443目标流量,因为有人认为混淆协议是个好主意(叹气)。我可以维护域列表并根据需要零星更新。

Stubby

由于我的边界防火墙是基于Ubuntu的设备,我需要找到可以监听DNS请求,然后将其制定为DNS over TLS(DoT)事务到Quad9的软件。我怀疑可能有很多选择,但我选择使用恰名为“Stubby”的DNS隐私守护进程(https://dnsprivacy.org/dns_privacy_daemon_-_stubby/)。安装就像“sudo apt install stubby”一样简单。

Stubby充当本地DNS隐私存根解析器,使用DoT通过加密的TLS连接发送DNS查询。Stubby通过名为/etc/stubby/stubby.yml的Yaml文件配置,正如你所料,Quad9发布了配置供你参考。更多信息请参阅https://support.quad9.net/hc/en-us/articles/4409217364237-DNS-over-TLS-Ubuntu-18-04-20-04-Stubby-。

Stubby配置文件 /etc/stubby/stubby.yml

如果你想查看所有各种设置,可以在这里找到:https://getdnsapi.net/documentation/manpages/stubby/。以下是一些亮点:

  • “tls_authentication: GETDNS_AUTHENTICATION_REQUIRED” 意味着必须使用TLS,没有回退。
  • “tls_query_padding_blocksize: 128” 将使用EDNS0选项填充到此数字以隐藏实际查询大小。
  • “edns_client_subnet_private: 1”(true)将防止任何客户端子网信息被发送到权威服务器。
  • “round_robin_upstreams: 1”(true)将以轮询方式将上游查询发送到所有指定的服务器。
  • “idle_timeout: 10000”(以毫秒指定)保持TCP连接打开该时间段以降低连接开销。可以被连接的服务端覆盖。
  • “listen_addresses” 是你的本地端监听地址。对于我自己的内部DNS服务器,将其设置为127.0.0.1端口8053是有意义的,这样我可以配置bind9使用它。

Bind配置

下一步是更改bind配置,使其将DNS请求“转发”到本地Stubby实例,而不是使用其他DNS名称服务器来填充其缓存。这里你有两个选项,要么转发所有请求,要么转发请求除非转发器失败,然后回退到正常DNS协议操作。就bind配置语法而言,这相当于使用指令“forward only”与“forward first”,后者将在失败时回退。你还需要配置你转发到的地址。下面的截图显示了我的配置,放置在/etc/bind/named.conf文件中的选项部分。

Bind Forward First配置

最后一步是确保Stubby正在运行,并确保Stubby配置为使用命令“systemctl enable stubby”作为根在系统服务中自动启动。

Stubby状态显示运行和启用

然后最后,你可以使用“rndc reload”重新加载你的bind名称服务器,现在你将加密到Quad9的互联网绑定DNS流量。

防火墙配置

在我的具体情况下,我使用iptables强制执行我的边界防火墙规则,因此,在我成功更新DNS配置后,我需要更改一些内容如下:

  • 允许出站TCP端口853流量到Quad9地址。
  • 配置一个包含常见DoH提供商的IP集,然后阻止到它们的流量。
  • 阻止任何未经授权的DNS直接发送到服务器而不使用内部DNS服务器。

我用来为DoH提供商列表创建IP集的一种可能方法是按域名列出提供商如上,然后每天对每个执行DNS查找,以确保如果提供商使用任播地址,阻止列表始终有一组当前的地址。使用简单的shell脚本和“ipset”命令提供了一种简单的方法来做到这一点。

用于创建/维护名为“doh”的IPSET的Shell脚本

在你有了这个配置之后,你可以轻松创建一个crontab条目,定期持续维护列表。

假设你的防火墙是边界设备,并且你正在执行NAT和IP流量转发,你需要某种iptables规则来阻止转发任何流量到DoH提供商列表。在我的配置中,这个规则如下所示:

阻止转发DoH流量的IP-Tables规则

你还需要确保Stubby可以从你的防火墙出站通信,以便其DNS over TLS流量能够针对Quad9服务器解析域。

允许DoT流量的出站防火墙规则

最后的点睛之笔是确保你网络内的任何端点不能完全绕过你的内部DNS服务器,并发送流量到互联网上的任何DNS提供商。许多Google生产的设备只是喜欢预先配置8.8.8.8作为其DNS解析器,这可能不会让你感到惊讶。这不会发生在我的网络上!

例如,如果你的内部网络范围在10.0.0.0/8 A类某处,一对类似于下面截图的规则将愉快地完成这一点。

阻止未经授权的DNS流量的规则

就这样!我通过加密互联网绑定的DNS流量,至少到Quad9,同时保持我自己监控网络内正常DNS流量的能力,获得了暂时的安心。我觉得这是加密、隐私、安全和操作可用性的公平平衡。

祝你在自己的 quest 中 Surviving the mess that is DNS over HTTPS 旅途愉快!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计