• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H03-May-2022-128105

cargo-crates/H03-May-2022-1,668,6081,331,072

src/H03-May-2022-345314

.gitignoreH A D29-Nov-197359 86

.travis.ymlH A D29-Nov-197344 54

Cargo.lockH A D01-Jan-197032.8 KiB1,3511,206

Cargo.tomlH A D01-Jan-19701.5 KiB5246

LICENSEH A D29-Nov-19731 KiB2217

README.mdH A D29-Nov-197310.5 KiB202128

localhost.pemH A D29-Nov-19732.7 KiB4847

test.shH A D29-Nov-1973366 62

README.md

1# doh-proxy
2
3A fast and secure DoH (DNS-over-HTTPS) and ODoH (Oblivious DoH) server.
4
5`doh-proxy` is written in Rust, and has been battle-tested in production since February 2018. It doesn't do DNS resolution on its own, but can sit in front of any DNS resolver in order to augment it with DoH support.
6
7## Installation
8
9### Option 1: precompiled binaries for Linux
10
11Precompiled tarballs and Debian packages for Linux/x86_64 [can be downloaded here](https://github.com/jedisct1/doh-server/releases/latest).
12
13### Option 2: from source code
14
15This requires the [`rust`](https://rustup.rs) compiler to be installed.
16
17* With built-in support for HTTPS (default):
18
19```sh
20cargo install doh-proxy
21```
22
23* Without built-in support for HTTPS:
24
25```sh
26cargo install doh-proxy --no-default-features
27```
28
29## Usage
30
31```text
32USAGE:
33    doh-proxy [FLAGS] [OPTIONS]
34
35FLAGS:
36    -O, --allow-odoh-post      Allow POST queries over ODoH even if they have been disabed for DoH
37    -K, --disable-keepalive    Disable keepalive
38    -P, --disable-post         Disable POST queries
39    -h, --help                 Prints help information
40    -V, --version              Prints version information
41
42OPTIONS:
43    -E, --err-ttl <err_ttl>                          TTL for errors, in seconds [default: 2]
44    -H, --hostname <hostname>                        Host name (not IP address) DoH clients will use to connect
45    -l, --listen-address <listen_address>            Address to listen to [default: 127.0.0.1:3000]
46    -b, --local-bind-address <local_bind_address>    Address to connect from
47    -c, --max-clients <max_clients>                  Maximum number of simultaneous clients [default: 512]
48    -C, --max-concurrent <max_concurrent>            Maximum number of concurrent requests per client [default: 16]
49    -X, --max-ttl <max_ttl>                          Maximum TTL, in seconds [default: 604800]
50    -T, --min-ttl <min_ttl>                          Minimum TTL, in seconds [default: 10]
51    -p, --path <path>                                URI path [default: /dns-query]
52    -g, --public-address <public_address>            External IP address DoH clients will connect to
53    -j, --public-port <public_port>                  External port DoH clients will connect to, if not 443
54    -u, --server-address <server_address>            Address to connect to [default: 9.9.9.9:53]
55    -t, --timeout <timeout>                          Timeout, in seconds [default: 10]
56    -I, --tls-cert-key-path <tls_cert_key_path>
57            Path to the PEM-encoded secret keys (only required for built-in TLS)
58
59    -i, --tls-cert-path <tls_cert_path>
60            Path to the PEM/PKCS#8-encoded certificates (only required for built-in TLS)
61```
62
63## HTTP/2 termination
64
65The recommended way to use `doh-proxy` is to use a TLS termination proxy (such as [hitch](https://github.com/varnish/hitch) or [relayd](https://bsd.plumbing/about.html)), a CDN or a web server with proxying abilities as a front-end.
66
67That way, the DoH service can be exposed as a virtual host, sharing the same IP addresses as existing websites.
68
69If `doh-proxy` and the HTTP/2 front-end run on the same host, using the HTTP protocol to communicate between both is fine.
70
71If both are on distinct networks, such as when using a CDN, `doh-proxy` can handle HTTPS requests, provided that it was compiled with the `tls` feature.
72
73The certificates and private keys must be encoded in PEM/PKCS#8 format. They can be stored in the same file.
74
75If you are using ECDSA certificates and ECDSA private keys start with `-----BEGIN EC PRIVATE KEY-----` and not `-----BEGIN PRIVATE KEY-----`, convert them to PKCS#8 with (in this example, `example.key` is the original file):
76
77```sh
78openssl pkcs8 -topk8 -nocrypt -in example.key -out example.pkcs8.pem
79```
80
81In order to enable built-in HTTPS support, add the `--tls-cert-path` option to specify the location of the certificates file, as well as the private keys file using `--tls-cert-key-path`.
82
83Once HTTPS is enabled, HTTP connections will not be accepted.
84
85A sample self-signed certificate [`localhost.pem`](https://github.com/jedisct1/doh-server/raw/master/localhost.pem) can be used for testing.
86The file also includes the private key.
87
88[`acme.sh`](https://github.com/acmesh-official/acme.sh) can be used to create and update TLS certificates using Let's Encrypt and other ACME-compliant providers. If you are using it to create ECDSA keys, see above for converting the secret key into PKCS#8.
89
90The certificates path must be set to the full certificates chain (`fullchain.cer`) and the key path to the secret keys (the `.key` file):
91
92```sh
93doh-proxy -i /path/to/fullchain.cer -I /path/to/domain.key ...
94```
95
96Once started, `doh-proxy` automatically reloads the certificates as they change; there is no need to restart the server.
97
98If clients are getting the `x509: certificate signed by unknown authority` error, double check that the certificate file is the full chain, not the other `.cer` file.
99
100## Accepting both DNSCrypt and DoH connections on port 443
101
102DNSCrypt is an alternative encrypted DNS protocol that is faster and more lightweight than DoH.
103
104Both DNSCrypt and DoH connections can be accepted on the same TCP port using [Encrypted DNS Server](https://github.com/jedisct1/encrypted-dns-server).
105
106Encrypted DNS Server forwards DoH queries to Nginx or `doh-proxy` when a TLS connection is detected, or directly responds to DNSCrypt queries.
107
108It also provides DNS caching, server-side filtering, metrics, and TCP connection reuse in order to mitigate exhaustion attacks.
109
110Unless the front-end is a CDN, an ideal setup is to use `doh-proxy` behind `Encrypted DNS Server`.
111
112## Oblivious DoH (ODoH)
113
114Oblivious DoH is similar to Anonymized DNSCrypt, but for DoH. It requires relays, but also upstream DoH servers that support the protocol.
115
116This proxy supports ODoH termination (not relaying) out of the box.
117
118However, ephemeral keys are currently only stored in memory. In a load-balanced configuration, sticky sessions must be used.
119
120Currently available ODoH relays only use `POST` queries.
121So, `POST` queries have been disabled for regular DoH queries, accepting them is required to be compatible with ODoH relays.
122
123This can be achieved with the `--allow-odoh-post` command-line switch.
124
125## Operational recommendations
126
127* DoH can be easily detected and blocked using SNI inspection. As a mitigation, DoH endpoints should preferably share the same virtual host as existing, popular websites, rather than being on dedicated virtual hosts.
128* When using DoH, DNS stamps should include a resolver IP address in order to remove a dependency on non-encrypted, non-authenticated, easy-to-block resolvers.
129* Unlike DNSCrypt where users must explicitly trust a DNS server's public key, the security of DoH relies on traditional public Certificate Authorities. Additional root certificates (required by governments, security software, enterprise gateways) installed on a client immediately make DoH vulnerable to MITM. In order to prevent this, DNS stamps should include the hash of the parent certificate.
130* TLS certificates are tied to host names. But domains expire, get reassigned and switch hands all the time. If a domain originally used for a DoH service gets a new, possibly malicious owner, clients still configured to use the service will blindly keep trusting it if the CA is the same. As a mitigation, the CA should sign an intermediate certificate (the only one present in the stamp), itself used to sign the name used by the DoH server. While commercial CAs offer this, Let's Encrypt currently doesn't.
131* Make sure that the front-end supports HTTP/2 and TLS 1.3.
132* Internal DoH servers still require TLS certificates. So, if you are planning to deploy an internal server, you need to set up an internal CA, or add self-signed certificates to every single client.
133
134## Example usage with `encrypted-dns-server`
135
136Add the following section to the configuration file:
137
138```toml
139[tls]
140upstream_addr = "127.0.0.1:3000"
141```
142
143## Example usage with `nginx`
144
145In an existing `server`, a `/doh` endpoint can be exposed that way:
146
147```text
148location /doh {
149  proxy_pass http://127.0.0.1:3000;
150}
151```
152
153This example assumes that the DoH proxy is listening locally to port `3000`.
154
155HTTP caching can be added (see the `proxy_cache_path` and `proxy_cache` directives in the Nginx documentation), but be aware that a DoH server will quickly create a gigantic amount of files.
156
157## DNS Stamp and certificate hashes
158
159Use the online [DNS stamp calculator](https://dnscrypt.info/stamps/) to compute the stamp for your server.
160
161Add it to the `[static]` section of [`dnscrypt-proxy`](https://github.com/DNSCrypt/dnscrypt-proxy) and check that everything works as expected.
162
163Then, start `dnscrypt-proxy` with the `-show-certs` command-line flag to print the hashes for your certificate chain.
164
165Here is an example output:
166
167```text
168[NOTICE] Advertised cert: [CN=dohtrial.att.net,O=AT&T Services\, Inc.,L=Dallas,ST=Texas,C=US] [f679e8451940f06141854dc94e1eb79fa5e04463c15b88f3b392da793c16c353]
169[NOTICE] Advertised cert: [CN=DigiCert Global CA G2,O=DigiCert Inc,C=US] [f61e576877da9650294cccb5f96c75fcb71bda1bbc4646367c4ebeda89d7318f]
170```
171
172The first printed certificate is the certificate of the server itself. The next line is the one that signed that certificate. As you keep going down, you are getting closer to the certificate authority.
173
174Unless you are using intermediate certificates, your safest option is probably to include the last printed hash certificate in your DNS stamp.
175
176Go back to the online DNS stamp calculator, and copy&paste the hash (in this example: `f61e576877da9650294cccb5f96c75fcb71bda1bbc4646367c4ebeda89d7318f`).
177
178If you are using Let's Encrypt, the last line is likely to be:
179
180```text
181Advertised cert: [CN=Let's Encrypt Authority R3,O=Let's Encrypt,C=US] [444ebd67bb83f8807b3921e938ac9178b882bd50aadb11231f044cf5f08df7ce]
182```
183
184There you have it. Your certificate hash is `444ebd67bb83f8807b3921e938ac9178b882bd50aadb11231f044cf5f08df7ce`.
185
186This [Go code snippet](https://gist.github.com/d6cb41742a1ceb54d48cc286f3d5c5fa) can also compute the hash of certificates given a `.der` file.
187
188### Common certificate hashes
189
190* Let's Encrypt R3:
191  * `444ebd67bb83f8807b3921e938ac9178b882bd50aadb11231f044cf5f08df7ce`
192* Let's Encrypt E1:
193  * `cc1060d39c8329b62b6fbc7d0d6df9309869b981e7e6392d5cd8fa408f4d80e6`
194
195## Clients
196
197`doh-proxy` can be used with [dnscrypt-proxy](https://github.com/DNSCrypt/dnscrypt-proxy) as a client.
198
199`doh-proxy` is used in production for the `doh.crypto.sx` public DNS resolver and many others.
200
201An extensive list of public DoH servers can be found here: [public encrypted DNS servers](https://github.com/DNSCrypt/dnscrypt-resolvers/blob/master/v3/public-resolvers.md).
202