Rust 语言打造的安全 DNS 解决方案:Hickory DNS

Rust 语言打造的安全 DNS 解决方案:Hickory DNS

在这个互联网高速发展的时代,DNS 作为网络世界的“电话簿”,其安全性和稳定性显得尤为重要。Hickory DNS 正是为了应对这一挑战而生。

项目起源

Hickory DNS 原本名为 Trust-DNS,后经过品牌重塑,加入了 hickory-dns 组织。它不仅继承了 Trust-DNS 的优秀基因,更在安全性和性能上进行了全面升级。

核心特性

  • 安全性:从底层代码开始,Hickory DNS 就注重安全性,避免使用可能导致程序崩溃的代码。
  • 稳定性:使用稳定的 Rust 语言,确保服务的稳定运行。
  • 易用性:简化操作流程,让 DNS 服务更容易管理和维护。

模块组成

Hickory DNS 由多个模块组成,每个模块都有其独特的功能和用途:

  • Hickory DNS:提供 DNS 权威服务器的运行工具。
  • Proto:底层 DNS 库,为其他 Hickory DNS 库提供支持。
  • Client:用于向 DNS 服务器发送查询、更新和通知消息。
  • Server:托管 DNS 记录,支持守护进程形式运行。
  • Resolver:执行 DNS 解析,可替代操作系统的默认解析服务。

功能亮点

Hickory DNS 支持多种高级功能,包括 DNSSEC 验证、原子记录创建、记录比较和交换等。服务器端还支持 DNS-over-TLS 和 DNS-over-HTTPS,为数据传输提供加密保护。

使用方法

这假定你已经安装了 Rust[1] 稳定版。这些假定 hickory-dns 代码库已经被同步到本地系统:

git clone https://github.com/hickory-dns/hickory-dns.git
cd hickory-dns

前提条件

最低 Rust 版本

  • 该项目当前的最低 rustc 版本为 1.67
  • OpenSSL 开发库(客户端和解析器中可选,最低版本 1.0.2)

Mac OS X: 使用 homebrew

  brew install openssl
  export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include
  export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib

基于 Debian 的系统(包括 Ubuntu & Raspbian): 使用 apt-get

  # 注意对于 openssl,TLS 需要至少 1.0.2 版本,
  # 如果这是问题,可以禁用 TLS(在客户端),见下文。
  $ apt-get install openssl
  $ apt-get install libssl-dev pkg-config

测试

Hickory DNS 使用 just 进行构建工作流管理。尽管在项目根目录运行 cargo test 可以工作,但这并不全面。使用 cargo install just 安装 just

  • 默认测试

    这些适合在本地系统上运行。它们将为本地测试创建套接字,但不会尝试访问远程系统。测试也可以从 crate 目录运行,例如 clientservercargo test

just default
  • 默认特性测试

    Hickory DNS 有许多特性,可以快速测试启用它们或不启用它们,支持三个目标,defaultno-default-featuresall-features

just all-features
  • 单独特性测试

    Hickory DNS 有许多特性,每个单独的特性都可以独立测试,查看各个 crates 了解它们所有的特性,这里是一个不一定最新的列表:dns-over-rustlsdns-over-https-rustlsdns-over-native-tlsdns-over-openssldns-dnssec-openssldns-dnssec-openssldns-dnssec-ringmdns。每个特性都可以使用它自己作为 just 的任务目标进行测试:

just dns-over-https-rustls
  • 基准测试

    等待 Rust 中的基准测试稳定。

构建

  • 生产构建,从 hickory-dns 基础目录开始,要获取所有特性,只需传递 --all-features 标志。
cargo build --release -p hickory-dns

运行

警告:Hickory DNS 仍在开发中,不建议在生产中运行。服务器目前仅是单线程的,它是非阻塞的,所以这应该允许它能够处理大多数内部负载。

  • 验证版本
./target/release/hickory-dns --version
  • 获取帮助
./target/release/hickory-dns --help
  • 使用测试配置启动 hickory-dns 服务器

你可能不希望传递 -p 参数将在默认 DNS 端口上运行。对于 tls 特性,也有那些端口选项,见 hickory-dns --help

./target/release/hickory-dns -c ./tests/test-data/test_configs/example.toml -z ./tests/test-data/test_configs/ -p 24141
  • 使用 dig 查询刚刚启动的服务器
dig @127.0.0.1 -p 24141 www.example.com

使用 hickory-resolver CLI

0.20 中可用

cargo install --bin resolve hickory-util

或从源代码,在 hickory-dns 目录中

cargo install --bin resolve --path util

示例:

$ resolve www.example.com.
Querying for www.example
.com. A from udp:8.8.8.8:53, tcp:8.8.8.8:53, udp:8.8.4.4:53, tcp:8.8.4.4:53, udp:[2001:4860:4860::8888]:53, tcp:[2001:4860:4860::8888]:53, udp:[2001:4860:4860::8844]:53, tcp:[2001:4860:4860::8844]:53
Success for query name: www.example.com. type: A class: IN
        www.example.com. 21063 IN A 93.184.215.14

作为依赖项和自定义特性使用

客户端有一些特性,出于不同的原因,在嵌入其他软件时可以禁用。

  • dnssec-openssl它是一个默认特性,所以需要将 default-features 设置为 false(这将禁用 hickory-dns 中所有其他默认特性)。在有其他加密库支持之前,这也会禁用 DNSSEC 验证。函数仍然存在,但在验证时总是返回错误。下面的例子将禁用所有默认特性并启用 OpenSSL,去掉 "openssl" 以去掉对 OpenSSL 的依赖。

  • dnssec-ringRing 支持可以用于 RSA 和 ED25519 DNSSEC 验证。

  • dns-over-native-tls使用 native-tls 实现 DNS-over-TLS,仅在客户端和解析器中支持,不在服务器中。

  • dns-over-openssl使用 openssl 实现 DNS-over-TLS,在服务器和客户端中支持,解析器没有默认的 CA 链。

  • dns-over-rustls使用 rustls 实现 DNS-over-TLS,仅在客户端和解析器中支持,不在服务器中。如果你希望使用纯 Rust 工具链,这是最佳选择。在客户端、解析器和服务器中支持。

  • dns-over-https-rustls使用 rustls 实现 DNS-over-HTTPS(并将启用 DNS-over-TLS),仅在客户端、解析器和服务器中支持。如果你希望使用纯 Rust 工具链,这是最佳选择。

  • mdns 实验性启用实验性的 mDNS 特性以及 DNS-SD。目前已知存在问题。

在依赖项中使用自定义特性:

[dependencies]
  ...
hickory-dns = { version = "*", default-features = false, features = ["dnssec-openssl"] }

在构建期间使用自定义特性:

$> cargo build --release --features dns-over-rustls
...

常见问题解答

  • 为什么你要再建一个 DNS 服务器?

    因为有 BIND 的所有安全通告。
    

    使用 Rust 语义,应该可以开发出一个高性能且安全的 DNS 服务器,更能抵御攻击。

  • 什么是 MSRV(最低稳定 Rust 版本)政策?

    Hickory DNS 将努力支持与三个 Rust 版本向后兼容。
    

    例如,如果 1.50 是当前版本,那么 MSRV 将是 1.47。版本只有在必要时才会增加,所以 MSRV 可能比这个政策所说的要旧。此外,MSRV 只支持 no-default-features 构建,因为试图在依赖项上执行此政策是一个棘手的问题。

Hickory DNS

Hickory DNS 是一个基于 Rust 语言构建的 DNS 客户端、服务器和解析器,从底层设计上就注重安全性和可靠性。

这个代码仓库包含多个不同的组件:

库名称 描述
Hickory DNS 用于运行 DNS 权威服务器的二进制文件。
Proto 原始 DNS 库,公开了不稳定的 API,仅供其他 Hickory DNS 库使用,不打算供最终用户使用。
Client 用于直接向 DNS 服务器发送 查询更新通知 消息。
Server 用于托管 DNS 记录,也有一个 hickory-dns 二进制文件用于以守护进程形式运行。
Resolver 利用客户端库执行 DNS 解析。可以替代标准操作系统解析功能。

注意 这个项目从 Trust-DNS 重新品牌为 Hickory DNS,并且已经转移到了 https://github.com/hickory-dns/hickory-dns 组织和代码仓库。

目标

  • 构建一个具有现代特性的安全 DNS 服务器和客户端。
  • 无恐慌(panics),所有代码都有保护。
  • 仅使用安全的 Rust,并以适当的错误处理避免所有恐慌。
  • 仅使用稳定的 Rust。
  • 防御一定程度的 DDOS 攻击。
  • 支持全局负载均衡功能选项。
  • 使其操作简单。

状态

解析器

Hickory DNS 解析器是 Rust 应用程序中的本地 Rust 实现的存根解析器。解析器支持许多常见的查询模式,所有这些都可以配置在创建解析器时。它能够使用 Unix 和 Windows 上的系统配置。在 Windows 上有一个已知的问题,与注册大量接口有关,因此可能需要忽略系统配置。

解析器将正确跟随 CNAME 链以及 SRV 记录查找。有一个长期计划使解析器能够完全递归查询,但目前还不可能。

客户端

Hickory DNS 客户端旨在直接用于操作 DNS 服务器。它可以用于验证记录或更新支持 SIG0 和动态更新的服务器上的记录。客户端还能够验证 DNSSEC。到目前为止,NSEC3 验证尚未支持,但 NSEC 是支持的。有两种接口可以使用,一种是兼容 async/await 的 AsyncClient,另一种是易于使用的阻塞 Client。今天,Tokio 是执行 Runtime 所必需的。

客户端唯一实现

这些是 DNS 协议支持的标准。客户端将它们作为高级接口实现,这比较少见。

特性 描述
SyncDnssecClient[2] DNSSEC 验证
create[3] 记录的原子创建,带有认证请求
append[4] 验证记录的存在并向其追加
compare_and_swap[5] 原子(取决于服务器)比较和交换
delete_by_rdata[6] 删除特定记录
delete_rrset[7] 删除整个记录集
delete_all[8] 删除具有给定名称的所有记录集
notify[9] 通知服务器重新加载区域

服务器

服务器代码已完成,守护进程支持 IPv4 和 IPv6,UDP 和 TCP。
目前没有办法限制 TCP 和 AXFR 操作,所以仍然不建议将其投入生产使用,因为 TCP 可以被用来 DOS 服务。
区域文件解析已完成并得到支持。目前没有分叉选项,服务器还没有线程化(尽管它使用异步 IO 实现,所以线程化可能没有太大好处)。在服务器可以被信任用于外部之前,还有很多工作要做。在私有网络的防火墙后面运行将是安全的。

区域签名支持已完成,要插入一个密钥存储,将带有 .key 后缀的 pem 编码 rsa 文件存储在初始区域文件所在的同一目录中。_注意_:这必须只能由当前用户读取。如果不存在,将会创建一个并写入到正确的位置。这也作为动态更新 SIG(0) 验证的初始密钥。要获取公钥,可以查询区域的 DNSKEY 记录。这需要提供给其他上游服务器以创建 DS 密钥。动态 DNS 也已完成,如果启用,将与区域文件一起存储带有 jrnl 后缀的日志文件。_注意_:如果密钥更改或更新,当前是操作员的责任从区域中删除唯一的公钥,这允许 DNSKEY 在密钥轮换期间存在一段不确定的时间。当前没有在线轮换密钥的选项,需要重启服务器进程。

服务器上的 DNS-over-TLS 和 DNS-over-HTTPS

服务器上的 TLS 支持是通过 pkcs12 der 文件管理的。文档在示例测试配置文件中捕获,example.toml[10]。服务器可以注册证书并使用 add_ca() 方法将其固定到客户端。或者,由于客户端使用 rust-native-tls 库,它应该可以与任何标准 CA 签名的证书一起使用。

DNS-over-TLS 和 DNS-over-HTTPS

DoT 和 DoH 都得到支持。这是通过使用 native-tlsopensslrustls(目前只有 rustls 支持 DoH)中的一个来实现的。解析器需要注册有效的 DoT 或 DoH 解析器才能使用。

要与 Client 一起使用,应该使用 TlsClientConnectionHttpsClientConnection。类似地,要与 tokio AsyncClient 一起使用,应该使用 TlsClientStreamHttpsClientStream。目前不支持客户端认证,mTLS,还有一些问题正在解决中。TLS 对于服务器认证和连接隐私很有用。

要启用 DoT,必须启用 dns-over-native-tlsdns-over-openssldns-over-rustls 中的一个功能,dns-over-https-rustls 用于 DoH。

DNSSEC 状态

目前,根密钥硬编码到系统中。这提供了 DNSKEY 和 DS 记录验证回根的能力。NSEC 已实现,但不是 NSEC3。
由于缓存尚未启用,已经注意到一些 DNS 服务器似乎限制了连接,验证 RRSIG 记录回根可能需要大量的额外查询来获取这些记录。

区域将在任何通过动态 DNS 的记录更新时自动重新签名。要启用 DNSSEC,必须启用 dnssec-openssldnssec-ring 中的一个功能。

实现的 RFC

  • RFC 8499[11]: 没有更多的主/从关系,以纪念 六月节[12]

基本操作

  • RFC 1035[13]: DNS 基础规范(查看解析器的缓存)
  • RFC 2308[14]: DNS 查询的负缓存(查看解析器)
  • RFC 2782[15]: 服务定位
  • RFC 3596[16]: IPv6
  • RFC 6891[17]: DNS 的扩展机制
  • RFC 6761[18]: 特殊用途域名(解析器)
  • RFC 6762[19]: mDNS 多播 DNS(实验功能:mdns
  • RFC 6763[20]: DNS-SD 服务发现(实验功能:mdns
  • RFC ANAME[21]: 特定地址的 DNS 别名(ANAME

更新操作

  • RFC 2136[22]: 动态更新
  • RFC 7477[23]: DNS 中的父子同步

安全 DNS 操作

  • RFC 2931[24]: SIG(0)
  • RFC 3007[25]: 安全动态更新
  • RFC 4034[26]: DNSSEC 资源记录
  • RFC 4035[27]: DNSSEC 的协议修改
  • RFC 4509[28]: DNSSEC 委托签名中的 SHA-256
  • RFC 5702[29]: DNSKEY 和 RRSIG 中用于 DNSSEC 的 SHA-2 算法与 RSA
  • RFC 6844[30]: DNS 认证机构授权(CAA)资源记录
  • RFC 6698[31]: 基于 DNS 的命名实体认证(DANE)传输层安全(TLS)协议:TLSA
  • RFC 6840[32]: DNSSEC 的澄清和实现说明
  • RFC 6944[33]: DNSKEY 算法实现状态
  • RFC 6975[34]: 信号加密算法理解
  • RFC 7858[35]: TLS 上的 DNS(特性:dns-over-rustlsdns-over-native-tls,或 dns-over-openssl
  • RFC DoH[36]: HTTPS 上的 DNS,DoH(特性:dns-over-https-rustls

正在进行或尚未实现的 RFC

基本操作

  • RFC 2317[37]: 无类 IN-ADDR.ARPA 委派

更新操作

  • RFC 1995[38]: 增量区域传输
  • RFC 1996[39]: 通知辅助服务器更新
  • Update Leases[40]: 动态 DNS 更新租约
  • Long-Lived Queries[41]: 带有通知的铃声

安全 DNS 操作

  • RFC 5155[42]: DNSSEC 哈希认证拒绝存在
  • DNSCrypt[43]: 受信任的 DNS 查询
  • S/MIME[44]: S/MIME 的域名

结语

Hickory DNS 是一个充满活力的开源项目,它不仅为 DNS 领域带来了新的选择,更为我们提供了一个更安全、更可靠的网络环境。

参考资料

[1]

Rust: https://www.rust-lang.org

[2]

SyncDnssecClient: https://docs.rs/hickory-client/latest/hickory_client/client/struct.SyncDnssecClient.html

[3]

create: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.create

[4]

append: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.append

[5]

compare_and_swap: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.compare_and_swap

[6]

delete_by_rdata: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.delete_by_rdata

[7]

delete_rrset: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.delete_rrset

[8]

delete_all: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.delete_all

[9]

notify: https://docs.rs/hickory-client/latest/hickory_client/client/trait.Client.html#method.notify

[10]

example.toml: https://github.com/hickory-dns/hickory-dns/blob/main/tests/test-data/test_configs/example.toml

[11]

RFC 8499: https://tools.ietf.org/html/rfc8499

[12]

六月节: https://en.wikipedia.org/wiki/Juneteenth

[13]

RFC 1035: https://tools.ietf.org/html/rfc1035

[14]

RFC 2308: https://tools.ietf.org/html/rfc2308

[15]

RFC 2782: https://tools.ietf.org/html/rfc2782

[16]

RFC 3596: https://tools.ietf.org/html/rfc3596

[17]

RFC 6891: https://tools.ietf.org/html/rfc6891

[18]

RFC 6761: https://tools.ietf.org/html/rfc6761

[19]

RFC 6762: https://tools.ietf.org/html/rfc6762

[20]

RFC 6763: https://tools.ietf.org/html/rfc6763

[21]

RFC ANAME: https://tools.ietf.org/html/draft-ietf-dnsop-aname-02

[22]

RFC 2136: https://tools.ietf.org/html/rfc2136

[23]

RFC 7477: https://tools.ietf.org/html/rfc7477

[24]

RFC 2931: https://datatracker.ietf.org/doc/html/rfc2931

[25]

RFC 3007: https://tools.ietf.org/html/rfc3007

[26]

RFC 4034: https://tools.ietf.org/html/rfc4034

[27]

RFC 4035: https://tools.ietf.org/html/rfc4035

[28]

RFC 4509: https://tools.ietf.org/html/rfc4509

[29]

RFC 5702: https://tools.ietf.org/html/rfc5702

[30]

RFC 6844: https://tools.ietf.org/html/rfc6844

[31]

RFC 6698: https://tools.ietf.org/html/rfc6698

[32]

RFC 6840: https://tools.ietf.org/html/rfc6840

[33]

RFC 6944: https://tools.ietf.org/html/rfc6944

[34]

RFC 6975: https://tools.ietf.org/html/rfc6975

[35]

RFC 7858: https://tools.ietf.org/html/rfc7858

[36]

RFC DoH: https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-14

[37]

RFC 2317: https://tools.ietf.org/html/rfc2317

[38]

RFC 1995: https://tools.ietf.org/html/rfc1995

[39]

RFC 1996: https://tools.ietf.org/html/rfc1996

[40]

Update Leases: https://tools.ietf.org/html/draft-sekar-dns-ul-01

[41]

Long-Lived Queries: https://tools.ietf.org/html/draft-sekar-dns-llq-01

[42]

RFC 5155: https://tools.ietf.org/html/rfc5155

[43]

DNSCrypt: https://dnscrypt.org

原创文章,作者:速盾高防cdn,如若转载,请注明出处:https://www.sudun.com/ask/87592.html

(0)
速盾高防cdn's avatar速盾高防cdn
上一篇 2024年6月2日 下午1:22
下一篇 2024年6月2日 下午1:25

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注