Files
nxdns/docs/how-to/enable-doh-and-dot.md
T

106 lines
3.9 KiB
Markdown

# Enable DoH and DoT
Besides plain DNS on port 53, nxdns can answer encrypted queries from your devices: DNS over HTTPS (DoH) on port 443 and DNS over TLS (DoT) on port 853. Both are off by default, and both need a certificate and its private key, as PEM files.
## 1. Get a certificate
Devices check the certificate against the name you give them, so use a certificate for a name you control, from an ACME client such as certbot, lego or Caddy. Android's Private DNS setting, for example, takes a hostname and needs a certificate a phone trusts.
To try it out first, a self-signed certificate is enough:
```sh
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout /etc/nxdns/key.pem -out /etc/nxdns/cert.pem -days 365 \
-subj "/CN=nxdns.lan" \
-addext "subjectAltName=DNS:nxdns.lan,IP:192.168.1.10"
```
Replace `nxdns.lan` and `192.168.1.10` with the name and address your devices will use.
The key must be readable by the user nxdns runs as, and by nobody else. Under systemd that is the `nxdns` user:
```sh
chown nxdns:nxdns /etc/nxdns/cert.pem /etc/nxdns/key.pem
chmod 0644 /etc/nxdns/cert.pem
chmod 0600 /etc/nxdns/key.pem
```
Under Docker, put both files in `etc-nxdns/` next to `compose.yaml` and give them to uid 65532 the same way, since the container cannot change the read-only mount itself.
## 2. Turn the listeners on
In file mode, add both sections to the configuration file:
```zon
.doh_server = .{
.enabled = true,
.cert_path = "/etc/nxdns/cert.pem",
.key_path = "/etc/nxdns/key.pem",
},
.dot_server = .{
.enabled = true,
.cert_path = "/etc/nxdns/cert.pem",
.key_path = "/etc/nxdns/key.pem",
},
```
In database mode, open **System** in the web interface, tick **enabled** under **DoH Server** and **DoT Server**, check the certificate and key paths, and save.
Both listeners bind every address on their standard ports by default; `bind` and `port` change that. The packaged systemd unit already allows binding ports below 1024. Under Docker, uncomment the `443` and `853` lines under `ports:` in `compose.yaml`.
## 3. Check and restart
In file mode, `check` loads the certificate and key the same way the listeners will:
```sh
nxdns check --config /etc/nxdns/config.zon
```
It fails when a file is unreadable or when the key does not belong to the certificate, and warns when the key is readable by others:
```
FAIL doh_server.key_path: '/etc/nxdns/other.pem': private key does not belong to the certificate
WARN dot_server.key_path: '/etc/nxdns/key.pem' is mode 644; a TLS key must be readable by its owner only
```
Then restart nxdns (`systemctl restart nxdns`, or `docker compose restart`). The log names both listeners:
```
info(nxdns): doh listener on 0.0.0.0:443
info(nxdns): dot listener on 0.0.0.0:853
```
If a certificate cannot be loaded, nxdns refuses to start and exits 2 rather than run without the listener you asked for:
```
doh_server: '/etc/nxdns/cert.pem' + '/etc/nxdns/key.pem': private key file is not readable
nxdns run failed: BadCertificate
```
## 4. Test them
DoT, with a `dig` from BIND 9.18 or newer:
```sh
dig @192.168.1.10 +tls example.com A +short
```
DoH, using curl's own DoH resolver to look up `example.com`:
```sh
curl -sS --doh-url https://nxdns.lan/dns-query -o /dev/null \
-w 'resolved to %{remote_ip}\n' https://example.com
```
Add `--doh-insecure` to the curl command while you test with a self-signed certificate. DoH is served at `/dns-query` only, over HTTP/1.1, as both GET and POST.
## Renewing the certificate
nxdns checks both files every 30 seconds and switches to a renewed pair on its own; connections already open finish on the old one. There is nothing to restart. Each reload is logged:
```
info(cert_store): certificate reloaded from /etc/nxdns/cert.pem
```
To load it at once instead, press **Reload certificates** on the **System** page. If a reload fails, nxdns keeps serving the certificate it has and says why.