#proxy-server #dns-server #dns-resolver #dns #proxy #doh #https

app doh-proxy

一个DNS-over-HTTPS (DoH) 和 ODoH (无感知DoH) 代理

45个版本

0.9.11 2024年7月3日
0.9.10 2023年7月15日
0.9.9 2023年4月14日
0.9.8 2023年2月19日
0.1.5 2018年2月12日

#74 in 网络编程

Download history 20/week @ 2024-05-13 5/week @ 2024-05-20 9/week @ 2024-05-27 29/week @ 2024-06-03 26/week @ 2024-06-10 22/week @ 2024-06-17 18/week @ 2024-06-24 261/week @ 2024-07-01 59/week @ 2024-07-08 29/week @ 2024-07-15 22/week @ 2024-07-22 300/week @ 2024-07-29 25/week @ 2024-08-05 40/week @ 2024-08-12

389次每月下载

MIT 协议

130KB
1.5K SLoC

DoH server (and ODoH - Oblivious DoH server)

一个快速且安全的DoH (DNS-over-HTTPS) 和 ODoH (无感知DoH) 服务器。

doh-proxy是用Rust编写的,自2018年2月以来已在生产环境中经过实战测试。它本身不进行DNS解析,但可以放在任何DNS解析器前面,以便通过DoH支持来增强它。

安装

选项1:Linux的预编译二进制文件

Linux/x86_64的预编译tar包和Debian包 可以在此下载

选项2:从源代码

这需要安装rust 编译器。

  • 内置HTTPS支持(默认)
cargo install doh-proxy
  • 无内置HTTPS支持
cargo install doh-proxy --no-default-features

用法

USAGE:
    doh-proxy [FLAGS] [OPTIONS]

FLAGS:
    -O, --allow-odoh-post      Allow POST queries over ODoH even if they have been disabed for DoH
    -K, --disable-keepalive    Disable keepalive
    -P, --disable-post         Disable POST queries
    -h, --help                 Prints help information
    -V, --version              Prints version information

OPTIONS:
    -E, --err-ttl <err_ttl>                          TTL for errors, in seconds [default: 2]
    -H, --hostname <hostname>                        Host name (not IP address) DoH clients will use to connect
    -l, --listen-address <listen_address>            Address to listen to [default: 127.0.0.1:3000]
    -b, --local-bind-address <local_bind_address>    Address to connect from
    -c, --max-clients <max_clients>                  Maximum number of simultaneous clients [default: 512]
    -C, --max-concurrent <max_concurrent>            Maximum number of concurrent requests per client [default: 16]
    -X, --max-ttl <max_ttl>                          Maximum TTL, in seconds [default: 604800]
    -T, --min-ttl <min_ttl>                          Minimum TTL, in seconds [default: 10]
    -p, --path <path>                                URI path [default: /dns-query]
    -g, --public-address <public_address>            External IP address DoH clients will connect to
    -j, --public-port <public_port>                  External port DoH clients will connect to, if not 443
    -u, --server-address <server_address>            Address to connect to [default: 9.9.9.9:53]
    -t, --timeout <timeout>                          Timeout, in seconds [default: 10]
    -I, --tls-cert-key-path <tls_cert_key_path>
            Path to the PEM-encoded secret keys (only required for built-in TLS)

    -i, --tls-cert-path <tls_cert_path>
            Path to the PEM/PKCS#8-encoded certificates (only required for built-in TLS)

示例命令行

doh-proxy -H 'doh.example.com' -u 127.0.0.1:53 -g 233.252.0.5

在此,doh.example.com 是主机名(应与TLS证书中包含的名称匹配),127.0.0.1:53 是DNS解析器的地址,233.252.0.5 是DoH服务器的公网IP地址。

HTTP/2和HTTP/3终止

推荐使用doh-proxy的方式是使用TLS终止代理(例如hitchrelayd),CDN或具有代理功能的Web服务器作为前端。

这样,DoH服务可以作为一个虚拟主机暴露出来,与现有网站共享相同的IP地址。

如果doh-proxy和HTTP/2(/ HTTP/3)前端运行在同一主机上,使用HTTP协议进行两者之间的通信是可行的。

如果两者位于不同的网络中,例如使用CDN时,只要在编译时启用了tls功能,doh-proxy可以处理HTTPS请求。

证书和私钥必须使用PEM/PKCS#8格式编码。它们可以存储在同一文件中。

如果您使用的是ECDSA证书,并且ECDSA私钥以-----BEGIN EC PRIVATE KEY-----开头,而不是以-----BEGIN PRIVATE KEY-----开头,则需要将它们转换为PKCS#8格式。以下是一个示例(在这个例子中,example.key是原始文件)

openssl pkcs8 -topk8 -nocrypt -in example.key -out example.pkcs8.pem

为了启用内置HTTPS支持,请添加--tls-cert-path选项以指定证书文件的位置,以及使用--tls-cert-key-path指定私钥文件的位置。

一旦启用HTTPS,将不接受HTTP连接。

一个示例自签名证书localhost.pem可用于测试。文件还包括私钥。

acme.sh可用于使用Let's Encrypt和其他ACME兼容提供商创建和更新TLS证书。如果您使用它创建ECDSA密钥,请参见上述内容以将密钥转换为PKCS#8。

证书路径必须设置为完整的证书链(fullchain.cer),密钥路径设置为私钥(.key文件)。

doh-proxy -i /path/to/fullchain.cer -I /path/to/domain.key ...

一旦启动,doh-proxy将自动重新加载证书,无需重新启动服务器。

如果客户端收到x509: 由未知机构签发的证书错误,请再次确认证书文件是完整的证书链,而不是其他.cer文件。

在443端口接受DNSCrypt和DoH连接

DNSCrypt是一种比DoH更快、更轻量级的加密DNS协议。

可以使用Encrypted DNS Server在同一TCP端口上接受DNSCrypt和DoH连接。

当检测到TLS连接时,Encrypted DNS Server将DoH查询转发到Nginx或doh-proxy,或者直接响应DNSCrypt查询。

它还提供了DNS缓存、服务器端过滤、指标和TCP连接重用,以减轻耗尽攻击。

除非前端是CDN,否则理想的设置是在Encrypted DNS Server之后使用doh-proxy

无意识DoH (ODoH)

无意识DoH与匿名DNSCrypt类似,但用于DoH。它需要中继站,但还需要支持该协议的上游DoH服务器。

此代理支持开箱即用的ODoH终止(非中继)。

然而,临时密钥目前仅存储在内存中。在负载均衡配置中,必须使用粘性会话。

目前可用的ODoH中继仅使用POST查询。因此,对于常规DoH查询已禁用POST查询,接受它们是兼容ODoH中继所必需的。

可以通过--allow-odoh-post命令行开关来实现。

操作建议

  • 可以通过SNI检查轻松检测和阻止DoH。作为一种缓解措施,DoH端点应尽可能与现有的、流行的网站共享同一个虚拟主机,而不是使用专用虚拟主机。
  • 当使用DoH时,DNS戳记应包括解析器IP地址,以消除对非加密、非认证、易于阻止的解析器的依赖。
  • 与DNSCrypt不同,用户必须明确信任DNS服务器公钥,DoH的安全性依赖于传统的公共证书颁发机构。客户端上安装的附加根证书(由政府、安全软件、企业网关所需)会立即使DoH易受中间人攻击。为了防止这种情况,DNS戳记应包括父证书的哈希值。
  • TLS证书与主机名相关联。但域名经常过期、重新分配和转让。如果一个原本用于DoH服务的域名获得了新的、可能是恶意的新所有者,如果CA相同,仍然配置为使用该服务的客户端将盲目继续信任它。作为一种缓解措施,CA应签名一个中间证书(仅在戳记中存在的一个),它本身用于签名DoH服务器使用的名称。虽然商业CA提供此功能,但Let's Encrypt目前不提供。
  • 确保前端至少支持HTTP/2和TLS 1.3。
  • 内部DoH服务器仍然需要TLS证书。因此,如果您计划部署内部服务器,您需要设置内部CA,或将自签名证书添加到每个客户端。

使用encrypted-dns-server的示例用法

将以下部分添加到配置文件中

[tls]
upstream_addr = "127.0.0.1:3000"

使用nginx的示例用法

在现有的server中,可以通过这种方式公开/dns-query端点

location /dns-query {
  proxy_pass http://127.0.0.1:3000;
}

此示例假设DoH代理正在本地监听端口号3000

可以添加HTTP缓存(请参阅Nginx文档中的proxy_cache_pathproxy_cache指令),但请注意,DoH服务器将很快创建大量文件。

DNS戳记和证书哈希

使用在线DNS戳记计算器计算您服务器的戳记。

将其添加到dnscrypt-proxy[static]部分,并检查一切是否按预期工作。

然后,使用命令行标志-show-certs启动dnscrypt-proxy,以打印您的证书链的哈希值。

以下是一个示例输出

[NOTICE] Advertised cert: [CN=dohtrial.att.net,O=AT&T Services\, Inc.,L=Dallas,ST=Texas,C=US] [f679e8451940f06141854dc94e1eb79fa5e04463c15b88f3b392da793c16c353]
[NOTICE] Advertised cert: [CN=DigiCert Global CA G2,O=DigiCert Inc,C=US] [f61e576877da9650294cccb5f96c75fcb71bda1bbc4646367c4ebeda89d7318f]

打印的第一个证书是服务器的证书。下一行是签名该证书的证书。随着你继续向下,你将接近证书颁发机构。

除非您使用中间证书,否则您最安全的选项可能是将最后打印的哈希证书包含在您的DNS戳记中。

返回在线DNS戳记计算器,并复制粘贴哈希(在此示例中:f61e576877da9650294cccb5f96c75fcb71bda1bbc4646367c4ebeda89d7318f)。

如果您使用Let's Encrypt,最后一行可能是

Advertised cert: [CN=Let's Encrypt Authority R3,O=Let's Encrypt,C=US] [444ebd67bb83f8807b3921e938ac9178b882bd50aadb11231f044cf5f08df7ce]

这就是了。您的证书哈希是 444ebd67bb83f8807b3921e938ac9178b882bd50aadb11231f044cf5f08df7ce

以下Go代码片段也可以根据.der文件计算证书的哈希。

常见证书哈希

  • Let's Encrypt E1
    • cc1060d39c8329b62b6fbc7d0d6df9309869b981e7e6392d5cd8fa408f4d80e6
  • Let's Encrypt R3
    • 444ebd67bb83f8807b3921e938ac9178b882bd50aadb11231f044cf5f08df7ce
  • Let's Encrypt R10
    • e644ba6963e335fe765cb9976b12b10eb54294b42477764ccb3a3acca3acb2fc
  • ZeroSSL
    • 9a3a34f727deb9bca51003d9ce9c39f8f27dd9c5242901c2bab1a44e635a0219

客户端

doh-proxy可以用作dnscrypt-proxy的客户端。

doh-proxy在生产中被用于doh.crypto.sx公共DNS解析器以及许多其他应用。

可以在这里找到公共DoH服务器的详尽列表:公共加密DNS服务器

依赖项

~15–29MB
~421K SLoC