You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 99e6e5f
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: draft-denis-dprive-dnscrypt.md
+95-21Lines changed: 95 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,9 +37,10 @@ The DNSCrypt protocol is designed to encrypt and authenticate DNS traffic betwee
37
37
38
38
# Introduction
39
39
40
-
The Domain Name System (DNS) {{!RFC1035}} is a critical component of Internet infrastructure, but its original design did not include security features to protect the confidentiality and integrity of queries and responses. This fundamental security gap exposes DNS traffic to eavesdropping, tampering, and various attacks that can compromise user privacy and network security.
41
-
42
-
To address these vulnerabilities, this document defines the DNSCrypt protocol, which encrypts and authenticates DNS queries and responses, providing strong confidentiality, integrity, and resistance to attacks affecting the original DNS protocol. The protocol is designed to be lightweight, extensible, and simple to implement securely on top of existing DNS infrastructure, offering a practical solution for securing DNS communications without requiring significant changes to current systems.
40
+
DNSCrypt encrypts and authenticates DNS traffic between clients and resolvers.
41
+
It uses signed resolver certificates, unauthenticated certificate retrieval,
42
+
authenticated encryption for queries and responses, and optional relaying
43
+
through Anonymized DNSCrypt.
43
44
44
45
# Conventions And Definitions
45
46
@@ -179,18 +180,18 @@ The protocol operates as follows:
179
180
180
181
1. The DNSCrypt client sends a DNS query to a DNSCrypt server to retrieve the server's certificates.
181
182
2. The client generates the client key-exchange value required by the selected certificate.
182
-
3. The client encrypts unmodified DNS queries using the selected certificate, padding them as necessary, and concatenates them to `<client-magic>`, `<client-pk>`, and `<client-nonce>`. The resulting output is transmitted to the server via standard DNS transport mechanisms {{!RFC1035}}.
183
+
3. The client encrypts unmodified DNS queries using the selected certificate, padding them as necessary, and concatenates them to `<client-magic>`, `<client-pk>`, and `<client-nonce>`. The resulting output is transmitted to the server over UDP or TCP.
183
184
4. Encrypted queries are decrypted by the server using the query's `<client-pk>` field and the resolver secret key corresponding to the selected certificate. The output is a regular DNS packet that doesn't require any special processing.
184
-
5. To send an encrypted response, the server adds padding to the unmodified response, encrypts the result using the shared key and a nonce made of the client's nonce followed by the resolver's nonce, and truncates the response if necessary. The resulting packet, truncated or not, is sent to the client using standard DNS mechanisms.
185
+
5. To send an encrypted response, the server adds padding to the unmodified response, encrypts the result using the shared key and a nonce made of the client's nonce followed by the resolver's nonce, and truncates the response if necessary. The resulting packet, truncated or not, is sent to the client over the same transport.
185
186
6. The client authenticates and decrypts the response using the shared key and the nonce included in the response. If the response was truncated, the client MAY adjust internal parameters and retry over TCP {{!RFC7766}}. If not, the output is a regular DNS response that can be directly forwarded to applications and stub resolvers.
186
187
187
188
Key features of the DNSCrypt protocol include:
188
189
189
-
- Stateless operation: Every query can be processed independently from other queries, with no session identifiers required.
190
-
- Flexible key management: Clients can replace their keys whenever they want, without extra interactions with servers.
191
-
- Proxy support: DNSCrypt packets can securely be proxied without having to be decrypted, allowing client IP addresses to be hidden from resolvers ("Anonymized DNSCrypt").
192
-
- Shared infrastructure: Recursive DNS servers can accept DNSCrypt queries on the same IP address and port used for regular DNS traffic.
193
-
- Attack mitigation: DNSCrypt mitigates two common security vulnerabilities in regular DNS over UDP: amplification {{!RFC5358}} and fragmentation attacks.
190
+
- Stateless operation: every query can be processed independently, with no session identifiers required.
191
+
- Fresh client key-exchange values: clients can generate new key-exchange values as often as allowed by the selected encryption system, without extra interactions with resolvers.
192
+
- Proxy support: DNSCrypt packets can be relayed without being decrypted, allowing client IP addresses to be hidden from resolvers with Anonymized DNSCrypt.
193
+
- Shared infrastructure: recursive DNS servers can accept DNSCrypt queries on the same IP address and port used for ordinary DNS traffic.
194
+
- Attack mitigation: DNSCrypt limits UDP response size, supports padding, and uses TCP retry to reduce amplification and fragmentation risk {{!RFC5358}}.
194
195
195
196
## Transport
196
197
@@ -199,8 +200,6 @@ DNSCrypt clients and resolvers SHOULD support the protocol via UDP, and MUST sup
199
200
200
201
Both TCP and UDP connections using DNSCrypt SHOULD employ port 443 by default.
201
202
202
-
The choice of port 443 helps DNSCrypt traffic blend with HTTPS traffic, providing some protection against traffic analysis.
203
-
204
203
## DNS Wire Conventions Used Here
205
204
206
205
Except where a cryptographic primitive explicitly says otherwise, all multi-byte
@@ -218,7 +217,7 @@ A DNS message starts with the 12-byte DNS header:
218
217
219
218
The DNS flags field uses the ordinary DNS bit assignments. The bits used by
220
219
this document are QR (`0x8000`), AA (`0x0400`), TC (`0x0200`), RD (`0x0100`),
221
-
and RA (`0x0080`).
220
+
RA (`0x0080`), and CD (`0x0010`).
222
221
223
222
A DNS name in a query is encoded as a sequence of labels. Each label is one
224
223
length octet, followed by that many bytes. The name ends with a zero length
@@ -245,6 +244,41 @@ character-string is a one-byte length followed by up to 255 bytes. A DNSCrypt
245
244
certificate carried in a `TXT` record is reconstructed by concatenating those
246
245
character-string payloads in order, excluding the one-byte length fields.
247
246
247
+
A successful certificate response echoes the single question and contains zero
248
+
or more `TXT` answer records, one certificate per answer record. A response that
249
+
does not contain the complete certificate set because of a UDP size limit sets
250
+
the DNS `TC` flag. A successful certificate response uses these DNS header
| NAME | `0xc0 0x0c`, or the uncompressed question name |
272
+
| TYPE | `TXT` (`0x00 0x10`) |
273
+
| CLASS | `IN` (`0x00 0x01`) |
274
+
| TTL | 4-byte DNS TTL; not the certificate validity |
275
+
| RDLENGTH | length in bytes of the TXT RDATA |
276
+
| RDATA | certificate split into TXT character-strings |
277
+
278
+
The response does not echo the query's EDNS(0) `OPT` pseudo-RR. Certificate
279
+
validity is determined only by `<ts-start>` and `<ts-end>` inside the signed
280
+
certificate, not by the DNS TTL.
281
+
248
282
When a UDP certificate query uses EDNS(0) padding, the additional record is an
249
283
`OPT`pseudo-RR. It has root owner name (`0x00`), type `OPT` (`0x00 0x29`), a
250
284
two-byte UDP payload size, four bytes of extended RCODE/version/flags, and an
@@ -290,7 +324,7 @@ source port.
290
324
After receiving a query, a resolver MAY ignore it or send an encrypted DNSCrypt
291
325
response.
292
326
293
-
The client MUST authenticate and, if authentication succeeds, decrypt the response with the help of the resolver's public key, the shared secret, and the response nonce. The client MUST verify that the `<client-nonce>` prefix of the response nonce matches a currently outstanding query. In case the response fails verification, or the `<client-nonce>` does not match a currently outstanding query, it MUST be disregarded by the client.
327
+
The client MUST authenticate and, if authentication succeeds, decrypt the response using the derived shared key and the response nonce. The client MUST verify that the `<client-nonce>` prefix of the response nonce matches a currently outstanding query. In case the response fails verification, or the `<client-nonce>` does not match a currently outstanding query, it MUST be disregarded by the client.
294
328
295
329
If the response has the TC flag set, the client MUST:
296
330
@@ -403,7 +437,7 @@ The following diagram shows the structure of a DNSCrypt certificate:
To initiate a DNSCrypt session, a client transmits an ordinary unencrypted `TXT` DNS query to the resolver's IP address and DNSCrypt port. A client MAY use UDP or TCP according to local policy. A common strategy is to try UDP first and retry over TCP after failure, timeout, or truncation.
440
+
To initiate a DNSCrypt session, a client transmits an ordinary unencrypted `TXT` DNS query to the resolver's IP address and DNSCrypt port. A client MAY use UDP or TCP according to local policy. A common strategy is to try UDP first and retry over TCP after failure, timeout, or truncation. Over TCP, the certificate query and response are DNS messages framed with the two-byte big-endian DNS-over-TCP length prefix {{!RFC7766}}; the prefix is not part of the DNS message.
407
441
408
442
Resolvers are not required to serve certificates both on UDP and TCP.
409
443
@@ -706,7 +740,7 @@ Relays MUST:
706
740
- Check that the target IP is not in a private, loopback, link-local, multicast, unspecified, or otherwise locally routed range
707
741
- Verify the port number is in an allowed range
708
742
- Ensure the inner `<dnscrypt-query>` doesn't start with `<anon-magic>`
709
-
- Reject the inner `<dnscrypt-query>` if its first 8 bytes are `0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01`, to avoid protocol confusion with QUIC {{!RFC9000}}; relays MAY reject broader reserved prefixes by local policy
743
+
- Reject the inner `<dnscrypt-query>` if its first 8 bytes are `0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01`, to avoid protocol confusion with QUIC {{!RFC9000}}
710
744
4. Forward the inner `<dnscrypt-query>` unmodified to the target server over UDP, without the Anonymized DNSCrypt prefix
711
745
5. Verify server responses:
712
746
@@ -717,7 +751,49 @@ Relays MUST:
717
751
718
752
Address validation is performed after decoding `<server-ip>`. If the decoded address is an IPv4-mapped IPv6 address, the relay applies the IPv4 policy to the embedded IPv4 address. Relay operators SHOULD maintain an explicit allowlist or denylist of target ranges. At minimum, relays MUST reject targets that are not globally routable, including unspecified, loopback, link-local, multicast, private-use, unique-local, documentation, benchmarking, and other special-use addresses.
719
753
720
-
These relay requirements ensure that anonymization does not compromise the security properties of the underlying DNSCrypt protocol. Proper deployment requires additional operational considerations.
754
+
If relay validation fails, the relay MUST NOT forward the inner packet. For a
755
+
UDP client, the relay sends no response. For a TCP client, the relay closes the
756
+
connection without sending a length-prefixed response. The same behavior applies
757
+
to upstream responses that fail validation or exceed the response-size rule.
758
+
759
+
The mandatory QUIC-confusion check above is intentionally the exact 8-byte
760
+
value. The broader rule that `<client-magic>` MUST NOT start with seven zero
761
+
bytes is enforced when resolvers issue certificates. A relay cannot classify
762
+
every inner packet by the first eight bytes alone, because the inner packet can
763
+
also be an unencrypted certificate query. Relay operators MAY reject broader
764
+
reserved prefixes by local policy after first recognizing valid certificate
765
+
queries.
766
+
767
+
A relay recognizes an inner certificate query by parsing it as a DNS message
768
+
with `QR = 0`, `QDCOUNT = 1`, question type `TXT`, question class `IN`, and a
769
+
question name that starts with `2.dnscrypt-cert.`. Relays are not required to
770
+
support non-standard provider names through Anonymized DNSCrypt; clients using
771
+
such names can retrieve certificates directly from the resolver.
772
+
773
+
An encrypted upstream response is valid for relaying if all of these are true:
774
+
775
+
- The response came from the target IP address and port selected by the prefix.
776
+
- The response is no larger than the inner query forwarded upstream.
777
+
- The response starts with `<resolver-magic>`.
778
+
779
+
No stronger encrypted-response matching is required at the relay. The relay
780
+
does not decrypt the packet, does not know the selected certificate, and cannot
781
+
in general know the offset of `<client-nonce>` because the `<client-pk>` length
782
+
depends on the encryption system and resumed PQ queries use a different shape.
783
+
The client performs nonce matching after decryption.
784
+
785
+
A certificate upstream response is valid for relaying if all of these are true:
786
+
787
+
- The response came from the target IP address and port selected by the prefix.
788
+
- The response is no larger than the inner certificate query forwarded upstream.
789
+
- The response is a DNS response (`QR = 1`) and has the same transaction ID as
790
+
the relayed certificate query.
791
+
- The response contains exactly one question whose name, type, and class match
792
+
the relayed certificate query.
793
+
- The matching question name starts with `2.dnscrypt-cert.`.
794
+
795
+
The relay does not need to validate certificate signatures or parse every TXT
796
+
answer. The client verifies certificates after receiving the relayed response.
721
797
722
798
## Operational Considerations
723
799
@@ -730,11 +806,9 @@ When using Anonymized DNSCrypt:
730
806
- Restrict allowed server ports (typically only allowing port 443)
731
807
- Monitor for abuse
732
808
733
-
These operational guidelines help ensure that Anonymized DNSCrypt deployments provide the intended privacy benefits while maintaining security and preventing abuse.
734
-
735
809
# Post-Quantum Key Exchange (PQDNSCrypt)
736
810
737
-
The key exchange described so far relies on X25519 {{!RFC7748}}, which a sufficiently capable quantum computer would be able to break. An attacker who records DNSCrypt traffic today could therefore decrypt it once such a computer exists. This section defines the PQ extension, which performs the key exchange with a hybrid post-quantum mechanism while leaving the rest of the protocol unchanged: the certificate system, the packet framing, the authenticated encryption, the nonces, the padding philosophy, and Anonymized DNSCrypt all carry over. A DNSCrypt deployment that uses this extension is referred to as PQDNSCrypt.
811
+
The classical `Box-XChaChaPoly` encryption system relies on X25519 {{!RFC7748}}, which a sufficiently capable quantum computer would be able to break. An attacker who records classical DNSCrypt traffic today could therefore decrypt it once such a computer exists. This section defines the PQ extension, which performs the key exchange with a hybrid post-quantum mechanism while leaving the rest of the protocol unchanged: the certificate system, the packet framing, the authenticated encryption, the nonces, the padding philosophy, and Anonymized DNSCrypt all carry over. A DNSCrypt deployment that uses this extension is referred to as PQDNSCrypt.
738
812
739
813
PQ is introduced as a new encryption system version (`<es-version>` `0x00 0x03`) inside the existing version 2 certificate format. It is not a new major protocol version, and it does not change the certificate lookup name. A resolver MAY advertise a PQ certificate alongside a classical certificate under the same provider name, and a client that does not implement PQ ignores the `<es-version>` value it does not recognize, exactly as already required.
740
814
@@ -1185,7 +1259,7 @@ The successful response carrying the 124-byte certificate above is 182 bytes. Th
1185
1259
1186
1260
~~~
1187
1261
certificate response with one TXT answer (182 bytes):
0 commit comments