|
| 1 | +Pi-hole can act as an encrypted resolver for the clients in your network. FTL answers DNS-over-TLS (DoT), DNS-over-HTTPS (DoH) and DNS-over-QUIC (DoQ) queries itself, so you no longer need a separate proxy in front of Pi-hole to offer encrypted DNS to your phones, laptops and routers. |
| 2 | + |
| 3 | +This page is about the *downstream* side, i.e., the encryption between your clients and your Pi-hole. It is unrelated to how Pi-hole talks to its own upstream servers. |
| 4 | + |
| 5 | +<!-- markdownlint-disable code-block-style --> |
| 6 | +!!! info "This is not the same as encrypting your upstream traffic" |
| 7 | + If you want the queries Pi-hole forwards to its upstream resolvers to be encrypted, see the guides for [unbound](../guides/dns/unbound.md), [cloudflared](../guides/dns/cloudflared.md) or [dnscrypt-proxy](../guides/dns/dnscrypt-proxy.md). Both directions can be encrypted independently of each other. |
| 8 | +<!-- markdownlint-enable code-block-style --> |
| 9 | + |
| 10 | +## What is served where |
| 11 | + |
| 12 | +Protocol | Standard | Transport | Default port | Config option |
| 13 | +---------|----------|----------------|----------------------------------|-------------- |
| 14 | +DoT | RFC 7858 | TCP | `853` | `dns.dot` |
| 15 | +DoQ | RFC 9250 | UDP (QUIC) | `853` | `dns.doq` |
| 16 | +DoH | RFC 8484 | TCP/UDP (HTTP) | the HTTPS port of the web server | `dns.doh` |
| 17 | + |
| 18 | +All three are enabled by default and all three use the same TLS certificate as the web interface (`webserver.tls.cert`, see [TLS/SSL](../api/tls.md)). |
| 19 | + |
| 20 | +DoT and DoQ share the port number `853` without colliding, as one uses TCP and the other UDP. Both ports are configurable, but we recommend staying with the defaults: `853` is the port assigned by the respective standard, and it is what clients try first (many of them do not even offer a field for a different port). Setting either option to `0` disables that listener. |
| 21 | + |
| 22 | +DoH has no port of its own. It is served at the path `/dns-query` on the web server's HTTPS port, i.e., the first entry in `webserver.port` carrying the `s` flag, so a Pi-hole reachable at `https://pi.hole/admin` answers DoH at `https://pi.hole/dns-query`. If you change the web server's HTTPS port, the DoH endpoint moves with it. |
| 23 | + |
| 24 | +## Enabling and disabling |
| 25 | + |
| 26 | +```bash |
| 27 | +sudo pihole-FTL --config dns.dot 853 # DoT on the standard port (default) |
| 28 | +sudo pihole-FTL --config dns.doq 853 # DoQ on the standard port (default) |
| 29 | +sudo pihole-FTL --config dns.doh true # DoH on the HTTPS web server port (default) |
| 30 | +``` |
| 31 | + |
| 32 | +Set `dns.dot` or `dns.doq` to `0`, or `dns.doh` to `false`, to switch the respective listener off. All three options require a restart of `pihole-FTL` to take effect. |
| 33 | + |
| 34 | +Who may query these listeners is governed by [`dns.listeningMode`](configfile.md), exactly like plain DNS on port 53: unless the mode is `ALL`, connections from outside your local network are dropped. This matters more here than for plain DNS, because encrypted resolvers are often reachable from the Internet by design - Pi-hole does not open itself up just because you enabled DoT. |
| 35 | + |
| 36 | +<!-- markdownlint-disable code-block-style --> |
| 37 | +!!! warning "Do not expose your Pi-hole to the Internet" |
| 38 | + An openly reachable resolver will be found and abused for amplification attacks. If you want to use your Pi-hole while away from home, put it behind a VPN, e.g., [WireGuard](../guides/vpn/wireguard/index.md), instead of forwarding port `853` in your router. |
| 39 | +<!-- markdownlint-enable code-block-style --> |
| 40 | + |
| 41 | +## Certificates |
| 42 | + |
| 43 | +All three protocols present the certificate configured in `webserver.tls.cert`. With the self-signed certificate Pi-hole generates for itself, clients will refuse the connection unless they trust Pi-hole's certificate authority - see [adding the CA to your browser or device](../api/tls.md#adding-the-ca-to-your-browser). Some clients are stricter than browsers here and accept a manually installed CA for DoT/DoQ only reluctantly or not at all, so a certificate from a public CA for a domain you own is the more comfortable route if you run into trouble. |
| 44 | + |
| 45 | +The name your clients use must match the certificate. If your certificate was created for `pi.hole` but the client is configured with an IP address, validation fails. |
| 46 | + |
| 47 | +## Using it from a client |
| 48 | + |
| 49 | +<!-- markdownlint-disable code-block-style --> |
| 50 | +???+ example "Testing from the command line" |
| 51 | + |
| 52 | + === "DoT" |
| 53 | + |
| 54 | + ```bash |
| 55 | + kdig +tls @pi.hole example.com |
| 56 | + ``` |
| 57 | + |
| 58 | + === "DoQ" |
| 59 | + |
| 60 | + ```bash |
| 61 | + kdig +quic @pi.hole example.com |
| 62 | + ``` |
| 63 | + |
| 64 | + === "DoH" |
| 65 | + |
| 66 | + ```bash |
| 67 | + curl -H 'accept: application/dns-message' \ |
| 68 | + 'https://pi.hole/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE' \ |
| 69 | + --output - |
| 70 | + ``` |
| 71 | + |
| 72 | + `kdig` is part of the `knot-dnsutils` package. Add `+tls-ca=/etc/pihole/tls_ca.crt` (or `curl --cacert ...`) if the client machine does not trust Pi-hole's CA yet. |
| 73 | +<!-- markdownlint-enable code-block-style --> |
| 74 | + |
| 75 | +Common places to enter these on real devices: |
| 76 | + |
| 77 | +- **Android** (9 and later): *Settings -> Network & internet -> Private DNS*, which speaks DoT and expects a hostname. |
| 78 | +- **iOS/macOS**: through a DNS profile, which can carry either a DoT or a DoH server. |
| 79 | +- **Firefox**: *Settings -> Privacy & Security -> DNS over HTTPS*, using `https://pi.hole/dns-query` as a custom provider. |
| 80 | +- **Routers**: many recent firmwares (OpenWrt, AVM FRITZ!OS, Unifi) can forward to a DoT server. |
| 81 | + |
| 82 | +Queries arriving this way show up in the query log like any other query, attributed to the client that sent them. |
| 83 | + |
| 84 | +## Requests over plain HTTP |
| 85 | + |
| 86 | +`/dns-query` is only served over HTTPS. A plaintext request is answered with `426 Upgrade Required` rather than being resolved, so a misconfigured client cannot silently fall back to sending your DNS traffic in the clear. |
0 commit comments