28 个稳定版本

3.1.2 2022 年 7 月 10 日
3.1.1 2021 年 12 月 28 日
3.1.0 2021 年 11 月 6 日
3.0.2 2021 年 4 月 4 日
1.1.5 2018 年 12 月 29 日

#1555网络编程

Download history 178/week @ 2024-03-30 29/week @ 2024-04-06

每月 61 次下载

BSD-3-Clause

80KB
2K SLoC

doh-client

doh-client 是一个 DNS over HTTPS 客户端,它打开一个本地的 UDP(DNS)端口并将所有 DNS 查询转发到一个远程的 HTTP/2.0 服务器。默认情况下,客户端将连接到 Cloudflare DNS 服务。它使用 Tokio 进行所有异步 IO 操作,并使用 Rustls 连接到 HTTPS 服务器。如果 --cache-size 不为零,客户端将使用私有 HTTP 缓存(参见 RFC 7234)来提高性能。 构建状态 依赖状态 最新版本 许可

入门

doh-client 使用 Rust 编写。要构建它,您需要 Rust 编译器和构建系统 cargo

构建

$ cargo build

或者以发行版构建

$ cargo build --release

默认情况下,启用了 socks5 代理(RFC 1928)。要构建不带该功能的客户端,请使用以下命令

$ cargo build --no-default-features

运行

要运行二进制文件,需要一个位置参数,如果 native-certs 功能未激活(请参阅 使用方法)。

$ ./doh-client /path/to/the/ca/file.pem

例如,如果您使用 Arch Linux,则以下命令使用系统证书存储

# ./doh-client /etc/ca-certificates/extracted/tls-ca-bundle.pem

Linux (systemd)

在Linux系统下,以systemd作为初始化系统,将doh-client作为守护进程运行且无需root权限,请按照以下说明操作。此示例将连接到Cloudflare DNS服务。

  1. 构建二进制文件(见构建)。
  2. 将二进制文件复制到/usr/bin作为root
    # cp target/release/doh-client /usr/bin/
    
  3. 将配置文件复制到/etc/systemd/system/作为root
    # cp doh-client.service doh-client.socket /etc/systemd/system
    
    如果二进制文件的位置与上面不同,则更改doh-client.service下的路径,该路径位于ExecStart。在配置文件doh-client.service中,CA文件的路径设置为/etc/ca-certificates/extracted/tls-ca-bundle.pem,在继续之前调整路径(如果使用Arch Linux,路径应该是正确的)。
  4. 重新加载systemd管理器配置
    # systemctl daemon-reload
    
  5. 启用doh-client作为守护进程
    # systemctl enable doh-client
    
  6. 重新启动系统或手动启动守护进程
    # systemctl start doh-client
    
  7. 通过添加以下行调整/etc/resolv.conf
    nameserver 127.0.0.1
    
附加

如果使用AppArmor,则可以从存储库应用doh-client配置文件。

  1. 将配置文件usr.bin.doh-client复制到/etc/apparmor.d/作为root
    # cp usr.bin.doh-client /etc/apparmor.d/
    
    如果CA文件的位置与/etc/ca-certificates/extracted/tls-ca-bundle.pem不同,则更改usr.bin.doh-client中的路径。
  2. 重新启动系统或重新加载所有配置文件
    # systemctl restart apparmor.service
    
Arch Linux

有一个可用的AUR软件包。

Mac OS (launchd)

在Mac OS下,以launchd作为初始化系统,将doh-client作为守护进程运行且无需root权限。此示例将连接到Cloudflare DNS服务。

  1. 构建二进制文件(见构建)。
  2. 将二进制文件复制到/usr/local/bin作为root
    # cp target/release/doh-client /usr/local/bin/
    
  3. launchd配置文件复制到/Library/LaunchDaemons/作为root
    # cp com.doh-client.daemon.plist /Library/LaunchDaemons
    
    如果二进制文件的位置与上面不同,则更改com.doh-client.daemon.plist下的路径,该路径位于ProgramArguments。在配置文件com.doh-client.daemon.plist中,CA文件的路径设置为/usr/local/share/doh-client/DigiCert_Global_Root_CA.pem,请从以下链接下载pem文件。在将pem文件复制到/usr/local/share/doh-client/之前,使用mkdir创建目录doh-client
  4. 按照以下步骤加载并启动配置文件
    # launchctl load -w /Library/LaunchDaemons/com.doh-client.daemon.plist
    
  5. 通过添加以下行调整/etc/resolv.conf
    nameserver 127.0.0.1
    

用法

doh-client有一个必需的位置参数,CAFILE,用于设置包含受信任CA证书的pem文件的路径。

$ ./doh-client --help
DNS over HTTPS client 3.1.2
LinkTed <[email protected]>
Open a local UDP (DNS) port and forward DNS queries to a remote HTTP/2.0 server.
By default, the client will connect to the Cloudflare DNS service.
This binary uses the env_logger as logger implementations.
See https://github.com/sebasmagri/env_logger/

USAGE:
    doh-client [OPTIONS] [CAFILE]

ARGS:
    <CAFILE>    The path to the pem file, which contains the trusted CA certificates
                If no path is given then the platform's native certificate store will be used

OPTIONS:
    -c, --cache-size <UNSIGNED LONG>
            The size of the private HTTP cache
            If the size is 0 then the private HTTP cache is not used (ignores cache-control)
            [default: 1024]

        --cache-fallback
            Use expired cache entries if no response is received from the server

        --client-auth-certs <CERTSFILE>
            The path to the pem file, which contains the certificates for the client authentication

        --client-auth-key <KEYFILE>
            The path to the pem file, which contains the key for the client authentication

    -d, --domain <Domain>
            The domain name of the remote server [default: cloudflare-dns.com]

    -g, --get
            Use the GET method for the HTTP/2.0 request

    -h, --help
            Print help information

    -l, --listen-addr <Addr:Port>
            Listen address [default: 127.0.0.1:53]

        --listen-activation
            Use file descriptor 3 under Unix as UDP socket or launch_activate_socket() under Mac OS

    -p, --path <STRING>
            The path of the URI [default: dns-query]

        --proxy-credentials <Username:Password>
            The credentials for the proxy

        --proxy-host <Addr/Domain:Port>
            Socks5 or HTTP CONNECT proxy host (see below)

        --proxy-https-cafile <CAFILE>
            The path to the pem file, which contains the trusted CA certificates for the https proxy
            If no path is given then the platform's native certificate store will be used

        --proxy-https-domain <Domain>
            The domain name of the https proxy

        --proxy-scheme <proxy-scheme>
            The protocol of the proxy [possible values: socks5, socks5h, http, https]

    -r, --remote-host <Addr/Domain:Port>
            Remote address/domain to the DOH server (see below) [default: 1.1.1.1:443]

        --retries <UNSIGNED INT>
            The number of retries to connect to the remote server [default: 3]

    -t, --timeout <UNSIGNED LONG>
            The time in seconds after that the connection would be closed if no response is received
            from the server [default: 2]

    -V, --version
            Print version information

CAUTION: If a domain name is used for a <Addr/Domain:Port> value instead of an IP address the system
resolver will be used to resolve the IP address of the domain name. If the `doh-client` is
configured as system resolver, then it will NOT WORK. It is recommended to always use an IP address
for <Addr/Domain:Port> values.

缓存性能

为了证明私有HTTP缓存(见RFC 7234)可以提高客户端性能,请向github.com发起请求

$ dig github.com +nocookie

; <<>> DiG 9.13.5 <<>> github.com +nocookie
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19752
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;github.com.            IN  A

;; ANSWER SECTION:
github.com.     8   IN  A   192.30.253.112
github.com.     8   IN  A   192.30.253.113

;; Query time: 35 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sa Jan 05 20:00:20 CET 2019
;; MSG SIZE  rcvd: 71

查询耗时35毫秒。如果再次发起请求(快速,在响应从缓存中移除之前)

$ dig github.com +nocookie

; <<>> DiG 9.13.5 <<>> github.com +nocookie
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52653
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;github.com.            IN  A

;; ANSWER SECTION:
github.com.     8   IN  A   192.30.253.112
github.com.     8   IN  A   192.30.253.113

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sa Jan 05 20:00:21 CET 2019
;; MSG SIZE  rcvd: 71

现在,查询耗时0毫秒,因为它被缓存了。

DNS请求和响应在缓存中有多长时间?

  1. 如果HTTP头中存在control-cache: max-age=XXX,则使用此值。例如,如果服务器响应为control-cache: max-age=100,则DNS请求和响应在缓存中保存100秒。100秒后,客户端将再次将请求转发到服务器。
  2. 如果不存在control-cache: max-age=XXX,则使用DNS响应中答案、授权和附加部分中的最小TTL。

许可证

本项目采用BSD-3-Clause许可证。

贡献

您有意提交给doh-client以包含在内的任何贡献,应作为BSD-3-Clause许可,不附加任何额外条款或条件。

依赖项

~18–31MB
~553K SLoC