Skip to content

Latest commit

 

History

History
677 lines (478 loc) · 45.6 KB

File metadata and controls

677 lines (478 loc) · 45.6 KB

六、Linux 上的 DNS 服务

域名系统(DNS)是当今信息化社会的重要支撑。 一个在技术团体中使用的谚语(俳句格式)如下:

不是 DNS

不可能是 DNS

DNS

这描述的技术问题比您想象的要多,包括广泛的互联网或云服务中断。 它还很好地描述了问题是如何解决的,答案是:“根本问题总是 DNS。” 这很好地说明了这项服务对当今企业网络和公共互联网的几乎各个方面是多么重要。

在本章中,我们将讨论几个涉及 DNS 基础知识的主题,然后是构建(最后是故障诊断)DNS 服务。 我们将着眼于以下领域:

  • 域名是什么?
  • 两个主要的 DNS 服务器实现
  • 常见的 DNS 实现
  • DNS 故障排除和侦察

然后,在介绍了 DNS 基础知识之后,我们将讨论以下两种全新的 DNS 实现,它们正在被迅速采用:

  • 超文本传输协议安全(HTTPS),即DoH
  • 传输层安全(TLS),即DoT

我们还将讨论DNS 安全扩展(DNSSEC)实现,它对 DNS 响应进行加密签名,以证明它们已被验证且未被篡改。

技术要求

通过本章的示例,您应该能够继续使用现有的 Linux 主机或虚拟机(VM)。 没有额外的要求。

什么是 DNS?

DNS 本质上是在人们想要什么和网络需要什么之间进行转换。 大多数情况下,人们理解主机和服务的文本名称——例如,google.compaypal.com。 然而,这些名称对底层网络没有任何意义。 DNS 所做的是把这些“完全限定的主机名”,说不定有人会因为你的类型到一个应用,如他们的浏览器开放系统互连(OSI)层 7(记得 OSI 层【显示】第三章,【病人】使用 Linux 和 Linux 工具网络诊断), 并将其转换为Internet 协议(IP)地址,然后可以用于路由 OSI 层 3 和 4 的应用请求。****

相反的方向,DNS 也可以将一个 IP 地址转化为完全限定域名**(FQDN),使用所谓的指针**(**【显示】PTR)请求(DNS PTR 记录)或“反向查找”。 这对于技术人员可能很重要,但是对于运行浏览器和其他应用的普通人来说,这些请求并不常见。****

两个主要的 DNS 服务器实现

DNS 在互联网上具有很大的和复杂的基础设施(我们将在本节中讨论这一点)。 这是由 13 个根域名服务器(每一个可靠的服务器集群),一组常用的名称服务器(例如,服务器我们使用谷歌或 Cloudflare),以及一系列的注册,费用,注册一个 DNS 域名(实例,您组织的域名。

然而,在大多数情况下,大多数管理员都是根据其组织的需要来工作的——使用面向内部人员的内部 DNS 名称服务器,或者使用面向 internet 的外部 DNS 名称服务器。 在本章中,我们将重点讨论这两个用例。 当我们构建这些示例时,您将看到谷歌或 Cloudflare DNS 基础设施,甚至根 DNS 服务器,并没有那么不同。

组织的“内部”DNS 服务器(及 DNS 概述)

组织部署的最常见的 DNS 服务是一个内部 DNS 服务器,供自己的人员使用。 该服务器可能有一个区域文件,其中填充了用于内部 DNS 解析的 DNS 记录。 该文件既可以通过编辑区域文件来手动填充,也可以通过客户端或通过动态主机配置协议(DHCP)租约使用自动注册来自动填充。 通常,这三种方法是结合在一起的。

基本的请求流很简单。 客户端发起 DNS 请求。 如果该请求是针对组织内部的主机且请求是针对内部 DNS 服务器,DNS 响应会立即提供,因为它在本地 DNS 服务器上。

如果它是用于外部主机,那么事情就有点复杂了—例如,让我们查询www.example.com。 在我们开始之前,请注意下面的图表显示了最坏的情况*,但是几乎每个步骤都有一个缓存过程,通常允许在这个过程中跳过一个或多个步骤:*

*Figure 6.1 – A dizzying overview of how complicated a single DNS request can get

图 6.1 -对单个 DNS 请求的复杂程度进行了令人眼花缭乱的概述

这个过程看起来相当复杂,但您会看到它进行得非常快,而且实际上有许多逃生口,在许多情况下,协议可以跳过这些步骤。 下面我们来详细看看整个最坏情况过程:

  1. 如果条目的 DNS 缓存内部 DNS 服务器,和时间生活(TTL)条目没有过期,然后立即响应提供给客户机。 类似地,如果客户机正在请求一个区域文件中托管在服务器上的条目,那么将立即向客户机提供答案。

  2. If the entry is not in the cache of the internal DNS server, or if it is in the cache but the TTL of that entry has expired, then the internal server forwards the request to its upstream providers (often called forwarders) to refresh the entry.

    如果查询在转发器的缓存中,它只会返回答案。 如果该服务器具有域的权威名称服务器,它将简单地查询该主机(跳过该过程,到步骤 5)。

  3. 如果转发器在缓存中没有请求,它将依次请求上游。 但是,在这种情况下,它可能会查询根名称服务器。 其中的目标是找到具有该域的实际条目(在区域文件中)的“权威名称服务器”。 在本例中,对.com的根名称服务器进行查询。

  4. 根名称服务器将不返回实际的答案,而是为顶级域(TLD)返回权威名称服务器——在本例中为.com返回。

  5. 在转发器获得此响应后,它使用该名称服务器条目更新其缓存,然后对该服务器进行实际查询。

  6. .com的授权服务器返回example.com的授权 DNS 服务器。

  7. 然后,转发器服务器对最终的权威名称服务器发出请求。

  8. example.com的权威名称服务器将实际查询*“answer”*返回给转发器服务器。

  9. 转发器名称服务器缓存该应答,然后将应答发送回您的内部名称服务器。

  10. Your internal DNS server also caches that answer, then forwards it back to the client.

客户端在其本地缓存中缓存请求,然后将请求的信息(DNS 响应)传递给请求它的应用(可能是您的 web 浏览器)。

同样,这个过程展示了最坏情况下的过程,即发出一个简单的 DNS 请求并接收一个回答。 在实践中,一旦服务器启动了,即使是很短的一段时间,缓存也会大大缩短这一过程。 一旦处于稳定状态,大多数组织的内部 DNS 服务器将缓存大多数请求,因此进程直接从步骤 1跳到步骤 10。 此外,你的转发 DNS 服务器会缓存——特别是,它几乎不会查询根名称服务器; 通常,它还会缓存 TLD 服务器(在本例中是.com的服务器)。

在这个描述中,我们还提出了“根名称服务器”的概念。 这些是根或.区域的权威服务器。 有 13 个根服务器用于冗余,每个根服务器实际上都是一个可靠的服务器集群。

我们需要在您的内部 DNS 服务器上启用哪些关键特性才能让所有这些工作? 我们需要启用以下功能:

  • DNS 递归:这个模型依赖于 DNS 递归,即每个服务器轮流使客户端的 DNS 请求“上线”。 如果请求的 DNS 条目没有在内部服务器上定义,它需要在上面转发这些请求的权限。

  • Forwarder entries: If the requested DNS entry is not hosted on the internal server, internal DNS service (iDNS) requests are forwarded to these configured IP addresses—these should be two or more reliable upstream DNS servers. These upstream servers will in turn cache DNS entries and expire them as their TTL timers expire. In days past, people would use their internet service provider's (ISP's) DNS servers for forwarders. In more modern times, the larger DNS providers are both more reliable and provide more features than your ISP. Some of the common DNS services used as forwarders are listed next (the most commonly used addresses appear in bold):

  • 缓存:在大型组织中,通过增加内存,DNS 服务器的性能可以大大提高——这允许更多的缓存,这意味着更多的请求可以直接从服务器的内存中本地处理。

  • Dynamic registration: While servers usually have static IP addresses and static DNS entries, it's common for workstations to have addresses assigned by DHCP, and having those workstations in DNS is of course desirable as well. DNS is often configured to allow dynamic registration of these hosts, either by populating DNS from DHCP addresses as they are assigned or by permitting the hosts to register themselves in DNS (as described in Request for Comments (RFC) 2136).

    微软在其动态更新过程中实现了身份验证机制,这也是它最常见的地方。 然而,它也是 Linux DNS(Berkeley Internet Name DomainBIND)中的一个选项。

  • 主机冗余:几乎所有核心业务都受益于冗余。 对于 DNS,通常使用第二个 DNS 服务器。 数据库通常按照一个方向进行复制(从主服务器到辅助服务器),并使用区域文件中的序列号来知道何时进行复制,使用一个称为区域传输的复制进程。 冗余是解释各种系统故障的关键,但它在允许系统维护而不中断服务方面也同样重要。

有了内部 DNS 服务器,在我们的配置中需要做哪些更改才能使 DNS 服务器向公共互联网提供区域服务?

面向 internet 的 DNS 服务器

在面向 internet 的 DNS 服务器的情况下,您很可能为一个或多个 DNS 区域实现权威 DNS 服务器。 例如,在我们的参考图(图 6.1)中,example.com的权威 DNS 服务器就是一个很好的例子。

在这个实现中,重点从内部服务器的性能和转发转移到限制访问以获得最大的安全性。 以下是我们想要实现的限制:

  • 限制递归:在我们概述的 DNS 模型中,这个服务器是“行尾”——它直接应答它所托管区域的 DNS 请求。 这个服务器永远不应该为了服务一个 DNS 请求而向上游查找。

  • 缓存不那么重要:如果您是一个组织,并且您正在托管自己的公共 DNS 区域,那么您只需要足够的内存来缓存自己的区域。

  • 主机冗余:同样,如果您正在托管自己的区域文件,添加另一个主机可能比添加缓存更重要。 这给您的 DNS 服务提供了一些硬件冗余,以便您可以在不中断服务的情况下在一台服务器上进行维护。

  • 限制区域传输:这是您想要实现的关键限制—您想要在单个 DNS 查询到达时回答它们。 因特网上的 DNS 客户端没有很好的理由为一个组织请求所有条目。 区域传输的目的是在冗余服务器之间维护区域,以便在编辑区域时,将更改复制到集群中的其他服务器。

  • Rate limiting: DNS servers have a feature called Response Rate Limiting (RRL) that limits how frequently any one source can query that server. Why would you implement such a feature?

    DNS 经常用于“欺骗”攻击。 由于它是基于用户数据报协议(UDP),没有“握手”来建立会话; 它是一个简单的请求/响应协议——因此,如果您想攻击一个已知的地址,您可以简单地将您的目标作为请求者进行 DNS 查询,而未经请求的应答将到达该 IP。

    这看上去不像一个攻击,但如果你再添加一个“乘数”(换句话说,如果你在做小的 DNS 请求和获得更大的响应实例,文本(TXT)记录和使用多个 DNS 服务器“反射”),然后你发送到目标的带宽可以增加很快。

    这使得速率限制非常重要—您希望限制任意一个 IP 地址每秒进行少量相同的查询。 这是一件合理的事情; 由于 DNS 缓存的依赖,任何一个 IP 地址在任何 5 分钟的时间内都不应该发出超过 1 到 2 个相同的请求,因为 5 分钟是任何 DNS 区域的最小 TTL。

    启用速率限制的另一个原因是,限制攻击者在 DNS 中进行侦察的能力——对常见 DNS 名称发出数十或数百个请求,并编译有效主机列表,以便随后对它们进行攻击。

  • 限制动态注册:当然,大多数面向 internet 的 DNS 服务器都不推荐动态注册。 一个例外是:将动态 DNS(DDNS)注册为服务的任何组织。 这种类型的公司包括 Dynu、DynDNS、FreeDNS 和 No-IP 等。 鉴于这些公司的专业性,它们各自都有自己的方法来确保 DDNS 更新(通常包括一个定制的代理和某种形式的认证)。 直接使用RFC 2136对于面向 internet 的 DNS 服务器来说是不安全的。

有了实现内部 DNS 服务器的基础知识,并开始为它们的各种用例提供安全保护,我们可以使用哪些 DNS 应用来构建 DNS 基础设施? 让我们在下一节中了解这一点。

常见的 DNS 实现

,也叫名为**(名守护进程),通常是 DNS 工具在 Linux 中实现的,可以说是最灵活和完整,以及最困难配置和故障诊断。 不管怎样,它是您在大多数组织中最可能看到和实现的服务。 两个主要的实现用例将在下两个部分中概述。**

DNS 伪装(dnsmasq)是一个竞争的 DNS 服务器实现。 它通常在网络设备上看到,因为它占用的空间小,但也为较小的组织提供了很好的 DNS 服务器。 关键优势 Dnsmasq 包括其内置的图形用户界面(GUI【显示】),可用于报告,以及它与 DHCP 的集成(我们将在下一章讨论),允许直接从 DHCP 域名注册数据库。 此外,Dnsmasq 实现了一种友好的方式来实现 DNS 阻塞列表,这些列表在 Pi-hole 应用中得到了很好的打包。 如果您的家庭网络在其外围防火墙或无线接入点(WAP)上有一个 DNS 服务器,该 DNS 服务器最有可能是 Dnsmasq。**

**在本章中,我们将关注常用的 BIND(或命名)DNS 服务器。 让我们继续使用该应用构建内部 DNS 服务器。

基本安装:BIND 内部使用

正如你所期望的,安装bind,即 Linux 中最流行的 DNS 服务器,就像下面这样简单:

$ sudo apt-get install –y bind9

看看这个/etc/bind/named.conf文件。 在旧版本中,应用的配置都在这个单一的配置文件中,但在新版本中,它只是由三行include组成,如下面的代码片段所示:

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";

编辑/etc/bind/named.conf.options,并添加以下选项——确保使用sudo,因为您需要管理员权限来更改bind的任何配置文件:

  • 允许从本地子网列表查询。 在本例中,我们允许RFC 1918中的所有子网,但是您应该将其限制为您环境中的子网。 注意,我们使用无类子网屏蔽来最小化本节中的条目数量。
  • 定义监听端口(在默认情况下是正确的)。
  • 使递归查询。
  • 定义一个 DNS 转发器列表以使递归工作。 在本例中,我们将为 DNS 转发添加谷歌和 Cloudflare。

完成之后,我们的配置文件应该如下所示。 请注意,它实际上是一个几乎“简单语言”的配置-没有什么神秘的任何这些部分的含义:

options {
  directory "/var/cache/bind";
  listen-on port 53 { localhost; };
  allow-query { localhost; 192.168.0.0/16; 10.0.0.0/8; 172.16.0.0/12; };
  forwarders { 8.8.8.8; 8.8.4.4; 1.1.1.1; };
  recursion yes;
}

接下来,编辑/etc/bind/named.conf.local,并添加服务器类型、区域和区域文件名。 同样,允许指定子网上的工作站使用allow-update参数向 DNS 服务器注册其 DNS 记录,如下面的代码片段所示:

zone "coherentsecurity.com" IN {
  type master;
  file "coherentsecurity.com.zone";
  allow-update { 192.168.0.0/16; 10.0.0.0/8;172.16.0.0/12 };
};

存储 DNS 记录的zone文件本身并不位于前两个config文件的相同位置。 要编辑zone文件,请编辑/var/cache/bind/<zone file name>—因此,在本例中,它是/var/cache/bind/coherentsecurity.com.zone。 您将再次需要sudo访问权限来编辑该文件。 进行以下更改:

  • 根据需要添加记录。
  • 用您的区域和名称服务器的 FQDN 更新SOA行。
  • 如果需要,更新SOA记录中最后一行的TTL值——默认值是86400秒(24 小时)。 这通常是一个很好的折中方案,因为它有利于跨多个服务器缓存记录。 但是,如果您正在进行任何 DNS 维护,您可能希望在前一天(即在维护之前 24 小时或更长时间)编辑文件,并将此时间缩短到 5 或 10 分钟,以便您的更改不会因为缓存而延迟。
  • 更新ns记录,它标识您域的 DNS 服务器。
  • 根据需要添加A记录—这些记录标识每个主机的 IP 地址。 注意,对于A记录,我们只对每个主机使用通用名称(CN),而没有使用包含域的 FQDN 名称。

一旦完成,我们的 DNS 区域文件应该如下所示:

Figure 6.2 – An example DNS zone file

图 6.2 - DNS 区域文件示例

正如我们前面讨论的,在内部 DNS 区域中,通常需要让客户端在 DNS 中注册自己。 这使得管理员可以通过名称访问客户端,而不必确定他们的 IP 地址。 这是对named.conf文件(或者,更可能是适用的包含子文件)的简单编辑。 注意,这需要我们将访问控制列表(acl)添加到 IP 地址的允许范围,以更新其 DNS 表项。 在本例中,我们将子网划分为静态 IP 和 dhcp 分配的客户端,但是一个简单的192.168.122.0/24ACL(定义整个子网)可能更常见。 定义整个公司的企业“超级网”也很常见——例如10.0.0.0/8192.168.0.0/16——但出于安全原因,通常不建议这样做; 你可能不需要在每个子网中自动注册设备。

在适用区域中,添加以下代码行:

acl dhcp-clients { 192.168.122.128/25; };
acl static-clients { 192.168.122.64/26; };
zone "coherentsecurity.com" {
    allow-update { dhcp-clients; static-clients; };
};

有几个脚本将检查您的工作—一个用于基本配置和包含的文件,另一个用于区域。 如果没有错误,named-checkconf将不返回任何文本,而named-checkzone将给您一些OK状态消息,如下所示。 如果您运行这些程序并且没有看到错误,那么您至少应该可以启动服务了。 注意,在下面的代码示例中,named-checkzone命令换行到下一行。 配置文件中的错误是常见的,例如缺少分号。 这些脚本对于发现的问题非常具体,但是如果它们出错了,而您需要更多信息,这些命令的日志文件(bind对于bind本身)是标准的/var/log/syslog文件,所以下面看一下:

$ named-checkconf
$ named-checkzone coherentsecurity.com /var/cache/bind/coherentsecurity.com.zone
zone coherentsecurity.com/IN: loaded serial 2021022401
OK

最后,启用bind9服务并通过运行以下命令启动它(如果您正在“推送”更新,则重新启动它):

sudo systemctl enable bind9
sudo systemctl start bind9

我们现在可以使用我们本地主机上的 DNS 服务器解析我们区域内的主机名,如下所示:

$ dig @127.0.0.1 +short ns01.coherentsecurity.com A
192.168.122.157
$ dig @127.0.0.1 +short esx01.coherentsecurity.com A
192.168.122.51

因为递归和转发器已经到位,我们也可以解析公共互联网上的主机,像这样:

$ dig @127.0.0.1 +short isc.sans.edu
45.60.31.34
45.60.103.34

随着我们内部的 DNS 服务器的完成和的工作,让我们来看看我们的面向互联网的 DNS,它将允许人们从公共互联网上解析我们公司的资源。

BIND:面向 internet 的实现细节

在我们开始之前,这个配置已经不像以前那么常见了。 回到 20 世纪 90 年代或更早的时候,如果你想让人们访问你的网络服务器,最常见的方法是站起来你自己的 DNS 服务器或使用你的 ISP 提供的一个。 在这两种情况下,任何 DNS 更改都是手动的文件编辑。

在最近的时代,通过 DNS 注册商托管你的 DNS 服务是很常见的。 这种“云”方法将安全实现留给了 DNS 提供商,并简化了维护,因为不同的提供商通常会给你一个 web 界面来维护你的区域文件。 关键安全考虑在这个模型中,您将希望一个提供者,让您可以选择启用多因素身份验证(MFA)(例如,使用谷歌身份验证或类似的),以防止凭据填料攻击你的管理访问权限。 这也值得研究你的注册商的帐户恢复程序-你不希望是通过实现 MFA 的所有工作,然后有一个攻击者偷了它与一个简单的帮助台呼叫你的 DNS 注册商!

综上所述,许多组织仍然有一个很好的用例来实现他们自己的 DNS 服务器,所以让我们继续修改我们从前面章节中获得的作为互联网 DNS 服务器的配置,如下:

  • 限速 DNS 请求:在etc/bind/named.conf.options中,我们希望添加某种形式的限速——在 DNS 的情况下,这是 RRL 算法。

  • 但是,请记住,这有可能拒绝为合法查询提供服务。 让我们添加一个10responses-per-second值作为初始速率限制,但将其设置为log-only的状态。 让它以log-only模式运行一段时间,并向上或向下调整每秒速率,直到您觉得有一个足够低的值来防止攻击性攻击,但又足够高,从而不会在合法操作期间拒绝访问。 如前所述,在此过程中要监视的日志文件是/var/log/syslog。 当你对自己的价值观满意时,删除log-only行。 一旦运行,请确保监视触发此设置的任何情况——这可以在日志记录或使用简单关键字匹配的安全信息和事件管理(SIEM)解决方案中轻松完成。 代码示例如下:

            rate-limit {
                 responses-per-second 10
                 log-only yes;
            }
  • 递归和转发:因为你只为有限数量的域提供 DNS 服务,所以你应该在/etc/bind/named.conf.options中禁用递归。 另外,完全删除 forwarders 行。 代码如下:

     recursion no;
  • 允许来自任何 IP 的查询:最后,我们不再限制访问我们的 DNS 服务器到内部域; 我们现在允许访问整个互联网,因此我们将更新allow-query行以反映这一点,如下所示:

既然我们已经为内部用户和互联网客户端提供了 DNS 服务器,那么我们可以使用哪些工具来排除该服务的故障呢?

DNS 故障排除和排查

在 Linux 中对 DNS 服务进行故障排除的主要工具是dig,它几乎预装在所有 Linux 发行版中。 如果您的发行版中没有dig,您可以使用apt-get install dnsutils来安装它。 这个工具的使用非常简单,如图所示:

Dig <request value you are making> <the request type you are making>  +<additional request types>

因此,要查找公司的名称服务器记录(我们将检查sans.org),我们将对sans.org进行ns查询,如下所示:

$ dig sans.org ns
; <<>> DiG 9.16.1-Ubuntu <<>> sans.org ns
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27639
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;sans.org.                      IN      NS
;; ANSWER SECTION:
sans.org.               86400   IN      NS      ns-1270.awsdns-30.org.
sans.org.               86400   IN      NS      ns-1746.awsdns-26.co.uk.
sans.org.               86400   IN      NS      ns-282.awsdns-35.com.
sans.org.               86400   IN      NS      ns-749.awsdns-29.net.
;; Query time: 360 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Fri Feb 12 12:02:26 PST 2021
;; MSG SIZE  rcvd: 174

这有很多注释的信息,知道设置了哪些 DNS 标志,以及 DNS 问题和答案的确切操作,这些信息都是非常有价值的,这些信息都在这个默认输出中。 然而,通常也需要一个“仅仅是事实”的输出——为了得到这个,我们将添加第二个参数+short,如下所示:

$ dig sans.org ns +short
ns-749.awsdns-29.net.
ns-282.awsdns-35.com.
ns-1746.awsdns-26.co.uk.
ns-1270.awsdns-30.org.

dig命令允许我们进行所喜欢的 DNS 查询。 你只能查询一个目标和一个 DNS 查询一次,不过,为了获得NS信息(有关**名称服务器)和【显示】邮件交换器(MX)信息,你将需要两个查询。 MX 查询显示在这里:**

$ dig sans.org mx +short
0 sans-org.mail.protection.outlook.com.

我们还可以使用哪些其他工具来进行故障排除,以及可能涉及哪些其他 DNS 实现?

DoH

DoH是一个较新的 DNS 协议; 顾名思义,它通过 HTTPS 传递,事实上,DNS 查询和响应在形式上类似于应用编程接口(API)。 这个新协议首先在许多浏览器中得到支持,而不是在主流操作系统中本地支持。 然而,它现在在大多数主流操作系统上都可用,只是在默认情况下没有启用而已。

为了远程验证 DoH 服务器,curl(“参见 url”的双关语)工具可以很好地完成这项工作。 在下面的例子中,我们正在查询 Cloudflare 的名称服务器:

$ curl -s -H 'accept: application/dns-json' 'https://1.1.1.1/dns-query?name=www.coherentsecurity.com&type=A'
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"www.coherentsecurity.com","type":1}],"Answer":[{"name":"www.coherentsecurity.com","type":5,"TTL":1693,"data":"robvandenbrink.github.io."},{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.108.153"},{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.109.153"},
{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.110.153"},{"name":"robvandenbrink.github.io","type":1,"TTL":3493,"data":"185.199.111.153"}]}

请注意,查询只是一个以以下方式组成的https请求:

https://<the dns server ip>/dns-query?name=<the dns query target>&type=<the dns request type>  

请求中的 HTTP 报头为accept: application/dns-json。 注意,该查询使用的是标准 HTTPS,所以它监听的是端口tcp/443,而不是常规的udp/53tcp/53DNS 端口。

我们可以通过管道将命令输出通过jq来提高其可读性。 这个简单的查询在输出中显示了标记—DNS 问题、答案和权限节。 注意,下面的代码片段RD国旗(代表递归)由客户端,和RA国旗(代表可用递归)设置的服务器:

curl -s -H 'accept: application/dns-json' 'https://1.1.1.1/dns-query?name=www.coherentsecurity.com&type=A' | jq
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": false,
  "CD": false,
  "Question": [
    {
      "name": "www.coherentsecurity.com",
      "type": 1
    }
  ],
  "Answer": [
    {
      "name": "www.coherentsecurity.com",
      "type": 5,
      "TTL": 1792,
      "data": "robvandenbrink.github.io."
    },
    ….  
    {
      "name": "robvandenbrink.github.io",
      "type": 1,
      "TTL": 3592,
      "data": "185.199.111.153"
    }
  ]
}

网络映射器(Nmap)还可以用于验证远程 DoH 服务器上的证书,如下代码片段所示:

nmap -p443 1.1.1.1 --script ssl-cert.nse
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-25 11:28 Eastern Standard Time
Nmap scan report for one.one.one.one (1.1.1.1)
Host is up (0.029s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-cert: Subject: commonName=cloudflare-dns.com/organizationName=Cloudflare, Inc./stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:cloudflare-dns.com, DNS:*.cloudflare-dns.com, DNS:one.one.one.one, IP Address:1.1.1.1, IP Address:1.0.0.1, IP Address:162.159.36.1, IP Address:162.159.46.1, IP Address:2606:4700:4700:0:0:0:0:1111, IP Address:2606:4700:4700:0:0:0:0:1001, IP Address:2606:4700:4700:0:0:0:0:64, IP Address:2606:4700:4700:0:0:0:0:6400
| Issuer: commonName=DigiCert TLS Hybrid ECC SHA384 2020 CA1/organizationName=DigiCert Inc/countryName=US
| Public Key type: unknown
| Public Key bits: 256
| Signature Algorithm: ecdsa-with-SHA384
| Not valid before: 2021-01-11T00:00:00
| Not valid after:  2022-01-18T23:59:59
| MD5:   fef6 c18c 02d0 1a14 ab75 1275 dd6a bc29
|_SHA-1: f1b3 8143 b992 6454 97cf 452f 8c1a c842 4979 4282
Nmap done: 1 IP address (1 host up) scanned in 7.41 seconds

然而,Nmap 的并没有提供一个脚本来通过执行一个实际的 DoH 查询来验证 DoH 本身。 为了填补这个空白,您可以在这里下载这样一个脚本:https://github.com/robvandenbrink/dns-doh.nse。

该脚本使用 Luahttp.shortport操作符验证端口是否正在服务 HTTP 请求,然后构造查询字符串,然后使用正确的头发出 HTTPS 请求。 关于这个工具的详细介绍可以在这里找到:https://isc.sans.edu/forums/diary/Fun+with+NMAP+NSE+Scripts+and+DOH+DNS+over+HTTPS/27026/。

深入研究了 DoH 之后,我们还有哪些其他协议可以用来验证和加密 DNS 请求和响应?

DoT

DoT是标准 DNS 协议,只是在 TLS 中封装。 点默认端口上实现tcp/853,这意味着它不会与域名冲突(udp/53tcp/53)或卫生署(tcp/443)——三个服务可以在同一个主机上运行如果 DNS 服务器应用支持所有三个。

大多数现代操作系统(作为客户机)都支持 DoT 名称解析。 默认情况下它并不总是运行,但如果不启用它,它是可用的。

远程验证 DoT 服务器就像使用 Nmap 来验证tcp/853是否在监听一样简单,如下面的代码片段所示:

$ nmap -p 853 8.8.8.8
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-21 13:33 PST
Nmap scan report for dns.google (8.8.8.8)
Host is up (0.023s latency).
PORT    STATE SERVICE
853/tcp open  domain-s
Doing a version scan gives us more good information, but the fingerprint (at the time of this book being published) is not in nmape:
$ nmap -p 853 -sV  8.8.8.8
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-21 13:33 PST
Nmap scan report for dns.google (8.8.8.8)
Host is up (0.020s latency).
PORT    STATE SERVICE    VERSION
853/tcp open  ssl/domain (generic dns response: NOTIMP)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port853-TCP:V=7.80%T=SSL%I=7%D=2/21%Time=6032D1B5%P=x86_64-pc-linux-gnu
SF:%r(DNSVersionBindReqTCP,20,"\0\x1e\0\x06\x81\x82\0\x01\0\0\0\0\0\0\x07v
SF:ersion\x04bind\0\0\x10\0\x03")%r(DNSStatusRequestTCP,E,"\0\x0c\0\0\x90\
SF:x04\0\0\0\0\0\0\0\0");
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.66 seconds

打开tcp/853港是标记为domain-s安全套接字层(DNS(【显示】SSL)),但这只是意味着端口号匹配条目的互联网工程任务组的**(【病人】IETF)表。 前面代码片段中显示的版本扫描(-sV)确实在响应中显示了DNSStatusRequestTCP字符串,这是一个很好的线索,表明该端口实际上正在运行 DoT。 因为它是 DoT,我们也可以使用 Nmap 来再次验证验证 DoT 服务的证书,如下所示:**

nmap -p853 --script ssl-cert 8.8.8.8
Starting Nmap 7.80 ( https://nmap.org ) at 2021-02-21 16:35 Eastern Standard Time
Nmap scan report for dns.google (8.8.8.8)
Host is up (0.017s latency).
PORT    STATE SERVICE
853/tcp open  domain-s
| ssl-cert: Subject: commonName=dns.google/organizationName=Google LLC/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:dns.google, DNS:*.dns.google.
com, DNS:8888.google, DNS:dns.google.com, DNS:dns64.dns.google, IP Address:2001:4860:4860:0:0:0:0:64, IP Address:2001:4860:4860:0:0:0:0:6464, IP Address:2001:4860:4860:0:0:0:0:8844, IP Address:2001:4860:4860:0:0:0:0:8888, IP Address:8.8.4.4, IP Address:8.8.8.8
| Issuer: commonName=GTS CA 1O1/organizationName=Google Trust Services/countryName=US
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-01-26T08:54:07
| Not valid after:  2021-04-20T08:54:06
| MD5:   9edd 82e5 5661 89c0 13a5 cced e040 c76d
|_SHA-1: 2e80 c54b 0c55 f8ad 3d61 f9ae af43 e70c 1e67 fafd
Nmap done: 1 IP address (1 host up) scanned in 7.68 seconds

到目前为止,我们所讨论的工具只能做到这一点。 dig工具(此时)不支持执行 DoT 查询。 然而,knot-dnsutils包为我们提供了一个“almostdig”命令行工具——kdig。 让我们使用这个工具来进一步研究 DoT。

结-dnsutils

knot-dnsutils是一个包含kdig工具的 Linux 包。 kdig复制了dig工具的功能,但也添加了其他功能,包括支持 DoT 查询。 要开始使用这个工具,我们首先必须安装knot-dnsutils包,如下所示:

sudo apt-get install  knot-dnsutils

现在安装完成了,正如前面提到的,kdig实用程序非常类似于dig命令,只是有一些额外的命令行参数——让我们通过一个 DoT 查询来说明这一点,如下所示:

kdig -d +short @8.8.8.8 www.cisco.com A  +tls-ca +tls-hostname=dns.google # +tls-sni=dns.google
;; DEBUG: Querying for owner(www.cisco.com.), class(1), type(1), server(8.8.8.8), port(853), protocol(TCP)
;; DEBUG: TLS, imported 129 system certificates
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, C=US,ST=California,L=Mountain View,O=Google LLC,CN=dns.google
;; DEBUG:      SHA-256 PIN: 0r0ZP20iM96B8DOUpVSlh5sYx9GT1NBVp181TmVKQ1Q=
;; DEBUG:  #2, C=US,O=Google Trust Services,CN=GTS CA 1O1
;; DEBUG:      SHA-256 PIN: YZPgTZ+woNCCCIW3LH2CxQeLzB/1m42QcCTBSdgayjs=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, The certificate is trusted.
www.cisco.com.akadns.net.
wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
e2867.dsca.akamaiedge.net.
23.66.161.25

我们使用了哪些新的参数?

参数debug(-d)给出了包含DEBUG字符串的所有前面的行。 鉴于由于其 TLS 支持,大多数人都将使用kdig,这些DEBUG行在测试新服务时为我们提供了一些很好的信息。 如果没有debug参数,我们的输出将更加“dig类似”,如下面的代码片段所示:

kdig  +short @8.8.8.8 www.cisco.com A  +tls-ca +tls-hostname=dns.google +tls-sni=dns.google
www.cisco.com.akadns.net.
wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
e2867.dsca.akamaiedge.net.
23.66.161.25

参数+short将输出缩短为“just The facts”显示,就像dig一样。 如果没有这个,输出将包括所有部分(不仅仅是“answer”部分),如下面的代码片段所示:

kdig @8.8.8.8 www.cisco.com A  +tls-ca +tls-hostname=dns.google +tls-sni=dns.google
;; TLS session (TLS1.3)-(ECDHE-X25519)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 57771
;; Flags: qr rd ra; QUERY: 1; ANSWER: 5; AUTHORITY: 0; ADDITIONAL: 1
;; EDNS PSEUDOSECTION:
;; Version: 0; flags: ; UDP size: 512 B; ext-rcode: NOERROR
;; PADDING: 240 B
;; QUESTION SECTION:
;; www.cisco.com.               IN      A
;; ANSWER SECTION:
www.cisco.com.          3571    IN      CNAME   www.cisco.com.akadns.net.
www.cisco.com.akadns.net.       120     IN      CNAME   wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.    13980   IN      CNAME   wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net. 2490        IN      CNAME  e2867.dsca.akamaiedge.net.
e2867.dsca.akamaiedge.net.      19      IN      A       23.66.161.25
;; Received 468 B
;; Time 2021-02-21 13:50:33 PST
;; From 8.8.8.8@853(TCP) in 121.4 ms

我们使用的新参数列在这里:

  • 参数+tls-ca强制 TLS 验证—换句话说,它验证证书。 默认情况下,将使用系统证书权威(CA)列表进行此操作。
  • 添加+tls-hostname允许指定 TLS 协商的主机名。 默认情况下,使用 DNS 服务器名称,但在我们的例子中,服务器的名字是8.8.8.8——你需要一个有效的主机名出现在CN主题选择名称(【显示】圣)名单 TLS 协商正确。 因此,这个参数允许您指定独立于服务器名称字段中使用的名称。
  • 添加+tls-sni会在请求中增加服务器名称指示(SNI)字段,这是许多 DoT 服务器所需要的。 这可能看起来很奇怪,因为 SNI 字段允许 HTTPS 服务器显示多个证书(每个证书针对不同的 HTTPS 站点)。

如果你不使用这些参数中的任何一个,而只像使用dig那样使用kdig会发生什么? 默认情况下,kdig不会强制针对您指定的 FQDN 进行证书验证,因此通常只会工作,如下代码片段所示:

$ kdig +short @8.8.8.8 www.cisco.com A
www.cisco.com.akadns.net.
wwwds.cisco.com.edgekey.net.
wwwds.cisco.com.edgekey.net.globalredir.akadns.net.
e2867.dsca.akamaiedge.net.
23.4.0.216

但是,按照预期的方式使用 TLS 是一个好主意,使用验证—毕竟,重点是在 DNS 结果中添加另一层信任。 如果您不验证服务器,那么您所做的就是加密查询和响应。 如果不在服务器名称字段或 TLS 主机名字段中指定正确的主机名(此值需要匹配证书参数),就无法进行验证。 强制进行证书验证是很重要的,因为这可以确保 DNS 服务器是您真正想要查询的服务器(也就是说,您的通信没有被拦截),并且响应在返回客户机的过程中没有被篡改。

既然我们了解了 DoT 是如何工作的,那么我们如何排除它或者发现 DNS 主机是否实现了 DoT ?

在 Nmap 中实现 DoT

与 DoH Nmap 示例类似,在 Nmap 中实现 DoT 允许在更大的范围内进行 DoT 发现和查询,而不是一次一个。 考虑到在 Nmap 中进行 HTTPS 调用的复杂性,实现这一点的一种简单方法是在 Nmap 脚本中使用 Lua 中的os.execute函数调用kdig

另一个关键的区别是,我们没有测试http功能的目标端口(使用shortport.http测试),而是使用shortport.ssl测试来验证为 SSL/TLS 功能发现的任何开放端口; 因为如果它不能服务有效的 TLS 请求,它就不能很好地是 DoT,对吗?

dns.dot工具可在此下载:

https://github.com/robvandenbrink/dns-dot

你可以在这里查看完整的文章:

https://isc.sans.edu/diary/Fun+with+DNS+over+TLS+%28DoT%29/27150

我们可以在 DNS 协议本身上实现哪些其他安全机制? 让我们来看看 DNSSEC,它是验证 DNS 响应的原始机制。

DNSSEC

DNSSEC是一种协议,它允许您验证服务器响应,使用区域证书而不是服务器证书来签署响应。 DNSSEC 仍然在udp/53tcp/53上运行,因为它不加密任何东西——它只是使用签名添加字段来验证标准 DNS 操作。

可以通过dig中的DNSKEY参数查看任意 DNS 区域的公钥。 在下面的代码示例中,我们添加了short参数:

$ dig DNSKEY @dns.google example.com +short
256 3 8 AwEAAa79LdJaZfIxVzyjq4H7yB4VqT/rIreB+N0jija+4bWHzNrwhSiu D/SOtgvX+gXEgwAR6tHGn9q9t65o85RfdHJrueORb0usa3x6LHM7qy6A r22P78UUn/rxa9jbi6yS4cVOzLnJ+OKO0w1Scly5XLDmmWPbIM2LvayR 2U4UAqZZ
257 3 8 AwEAAZ0aqu1rJ6orJynrRfNpPmayJZoAx9Ic2/Rl9VQWLMHyjxxem3VU SoNUIFXERQbj0A9Ogp0zDM9YIccKLRd6LmWiDCt7UJQxVdD+heb5Ec4q lqGmyX9MDabkvX2NvMwsUecbYBq8oXeTT9LRmCUt9KUt/WOi6DKECxoG /bWTykrXyBR8elD+SQY43OAVjlWrVltHxgp4/rhBCvRbmdflunaPIgu2 7eE2U4myDSLT8a4A0rB5uHG4PkOa9dIRs9y00M2mWf4lyPee7vi5few2 dbayHXmieGcaAHrx76NGAABeY393xjlmDNcUkF1gpNWUla4fWZbbaYQz A93mLdrng+M=
257 3 8 AwEAAbOFAxl+Lkt0UMglZizKEC1AxUu8zlj65KYatR5wBWMrh18TYzK/ ig6Y1t5YTWCO68bynorpNu9fqNFALX7bVl9/gybA0v0EhF+dgXmoUfRX 7ksMGgBvtfa2/Y9a3klXNLqkTszIQ4PEMVCjtryl19Be9/PkFeC9ITjg MRQsQhmB39eyMYnal+f3bUxKk4fq7cuEU0dbRpue4H/N6jPucXWOwiMA kTJhghqgy+o9FfIp+tR/emKao94/wpVXDcPf5B18j7xz2SvTTxiuqCzC MtsxnikZHcoh1j4g+Y1B8zIMIvrEM+pZGhh/Yuf4RwCBgaYCi9hpiMWV vS4WBzx0/lU=

要查看委托签名(DS)记录,使用DS参数,如下面的代码片段所示:

$ dig +short DS @dns.google example.com
31589 8 1 3490A6806D47F17A34C29E2CE80E8A999FFBE4BE
31589 8 2 CDE0D742D6998AA554A92D890F8184C698CFAC8A26FA59875A990C03 
E576343C
43547 8 1 B6225AB2CC613E0DCA7962BDC2342EA4F1B56083
43547 8 2 615A64233543F66F44D68933625B17497C89A70E858ED76A2145997E DF96A918
31406 8 1 189968811E6EBA862DD6C209F75623D8D9ED9142
31406 8 2 F78CF3344F72137235098ECBBD08947C2C9001C7F6A085A17F518B5D 8F6B916D

如果我们添加-d(debug)参数和过滤器来只查看DEBUG数据,我们将在输出中看到以下一行,表明我们正在使用与常规 DNS 查询相同的端口和协议:

dig -d DNSKEY @dns.google example.com  | grep DEBUG
;; DEBUG: Querying for owner(example.com.), class(1), type(48), server(dns.google), port(53), protocol(UDP)

要进行 DNSSEC 查询,只需在dig命令行中添加+dnssec,如下所示:

$ dig +dnssec +short @dns.google www.example.com A
93.184.216.34
A 8 3 86400 20210316085034 20210223165712 45150 example.com. UyyNiGG0WDAsberOUza21vYos8vDc6aLq8FV9lvJT4YRBn6V8CTd3cdo ljXV5uETcD54tuv1kLZWg7YZxSQDGFeNC3luZFkbrWAqPbHXy4D7Tdey LBK0R3xywGxgZIEfp9HMjpZpikFQuKC/iFvd14uJhoquMqFPFvTfJB/s XJ8=

DNSSEC 是关于对客户端和服务器之间的 DNS 请求进行认证,以及请求在服务器之间中继。 正如我们所看到的,它是由任何特定区域的所有者实现的,以允许请求者验证他们得到的 DNS“答案”是否正确。 然而,由于它的复杂性和对证书的依赖,它还没有看到交通部和 DoH 所拥有的吸收。

正如我们所见,DoT 和 DoH 关注的是个人隐私,对一个人在处理业务时发出的个人 DNS 请求进行加密。 虽然这种加密使这些 DNS 请求在发出时更难捕获,但这些请求仍然记录在 DNS 服务器本身上。 此外,如果攻击者能够收集一个人的 DNS 请求,他们也能够简单地记录他们访问的站点(通过 IP 地址)。

综上所述,我们不会深入探究 DNSSEC,主要是因为作为一个行业,我们已经做出了同样的决定,(在很大程度上)选择不执行它。 但是,您肯定会不时地看到它,特别是在处理涉及 DNS 的问题时,所以了解它的样子以及为什么可能实现它是很重要的。

总结

随着我们对 DNS 的讨论接近尾声,您现在应该已经拥有了构建基本的内部 DNS 服务器和面向互联网的标准 DNS 服务器的工具。 您还应该拥有通过编辑 Linuxbind或命名服务的各种配置文件来启动保护这些服务的基本工具。

此外,您应该熟悉使用digkdigcurlnmap等工具对各种 DNS 服务进行故障排除。

在下一章中,我们将继续讨论 DHCP,正如我们在本章中所看到的,它绝对是独立的,但仍然可以与 DNS 相关。

问题

正如我们总结的,这里有一个问题列表,供你测试你对本章材料的知识。 你可以在附录的评估部分找到答案:

  1. DNSSEC 与 DoT 有何不同?
  2. DoH 与“常规”DNS 有何不同?
  3. 您将通过外部 DNS 服务器在内部 DNS 服务器上实现哪些特性?

进一步阅读

欲知更多有关这方面的资料: