DoQ connections are established as described in the QUIC transport specification [RFC 9000
]. During connection establishment, DoQ support is indicated by selecting the Application-Layer Protocol Negotiation (ALPN) token "doq" in the crypto handshake.
By default, a DNS server that supports DoQ MUST
listen for and accept QUIC connections on the dedicated UDP port 853 (Section 8
), unless there is a mutual agreement to use another port.
By default, a DNS client desiring to use DoQ with a particular server MUST
establish a QUIC connection to UDP port 853 on the server, unless there is a mutual agreement to use another port.
DoQ connections MUST NOT
use UDP port 53. This recommendation against use of port 53 for DoQ is to avoid confusion between DoQ and the use of DNS over UDP [RFC 1035
]. The risk of confusion exists even if two parties agreed on port 53, as other parties without knowledge of that agreement might still try to use that port.
In the stub to recursive scenario, the use of port 443 as a mutually agreed alternative port can be operationally beneficial, since port 443 is used by many services using QUIC and HTTP-3 and is thus less likely to be blocked than other ports. Several mechanisms for stubs to discover recursives offering encrypted transports, including the use of custom ports, are the subject of ongoing work.
The mapping of DNS traffic over QUIC streams takes advantage of the QUIC stream features detailed in Section 2
of RFC 9000
, the QUIC transport specification.
DNS query/response traffic [RFC 1034
] [RFC 1035
] follows a simple pattern in which the client sends a query, and the server provides one or more responses (multiple responses can occur in zone transfers).
The mapping specified here requires that the client select a separate QUIC stream for each query. The server then uses the same stream to provide all the response messages for that query. In order for multiple responses to be parsed, a 2-octet length field is used in exactly the same way as the 2-octet length field defined for DNS over TCP [RFC 1035
]. The practical result of this is that the content of each QUIC stream is exactly the same as the content of a TCP connection that would manage exactly one query.
All DNS messages (queries and responses) sent over DoQ connections MUST
be encoded as a 2-octet length field followed by the message content as specified in [RFC 1035
The client MUST
select the next available client-initiated bidirectional stream for each subsequent query on a QUIC connection, in conformance with the QUIC transport specification [RFC 9000
]. Packet losses and other network events might cause queries to arrive in a different order. Servers SHOULD
process queries as they arrive, as not doing so would cause unnecessary delays.
The client MUST
send the DNS query over the selected stream and MUST
indicate through the STREAM FIN mechanism that no further data will be sent on that stream.
The server MUST
send the response(s) on the same stream and MUST
indicate, after the last response, through the STREAM FIN mechanism that no further data will be sent on that stream.
Therefore, a single DNS transaction consumes a single bidirectional client-initiated stream. This means that the client's first query occurs on QUIC stream 0, the second on 4, and so on (see Section 2.1
of RFC 9000
defer processing of a query until the STREAM FIN has been indicated on the stream selected by the client.
Servers and clients MAY
monitor the number of "dangling" streams. These are open streams where the following events have not occurred after implementation-defined timeouts:
the expected queries or responses have not been received or,
the expected queries or responses have been received but not the STREAM FIN
impose a limit on the number of such dangling streams. If limits are encountered, implementations MAY
close the connection.
When sending queries over a QUIC connection, the DNS Message ID MUST
be set to 0. The stream mapping for DoQ allows for unambiguous correlation of queries and responses, so the Message ID field is not required.
This has implications for proxying DoQ messages to and from other transports. For example, proxies may have to manage the fact that DoQ can support a larger number of outstanding queries on a single connection than, for example, DNS over TCP, because DoQ is not limited by the Message ID space. This issue already exists for DoH, where a Message ID of 0 is recommended.
When forwarding a DNS message from DoQ over another transport, a DNS Message ID MUST
be generated according to the rules of the protocol that is in use. When forwarding a DNS message from another transport over DoQ, the Message ID MUST
be set to 0.
The following error codes are defined for use when abruptly terminating streams, for use as application protocol error codes when aborting reading of streams, or for immediately closing connections:
No error. This is used when the connection or stream needs to be closed, but there is no error to signal.
The DoQ implementation encountered an internal error and is incapable of pursuing the transaction or the connection.
The DoQ implementation encountered a protocol error and is forcibly aborting the connection.
A DoQ client uses this to signal that it wants to cancel an outstanding transaction.
A DoQ implementation uses this to signal when closing a connection due to excessive load.
A DoQ implementation uses this in the absence of a more specific error code.
An alternative error code used for tests.
See Section 8.4
for details on registering new error codes.
In QUIC, sending STOP_SENDING requests that a peer cease transmission on a stream. If a DoQ client wishes to cancel an outstanding request, it MUST
issue a QUIC STOP_SENDING, and it SHOULD
use the error code DOQ_REQUEST_CANCELLED. It MAY
use a more specific error code registered according to Section 8.4
. The STOP_SENDING request may be sent at any time but will have no effect if the server response has already been sent, in which case the client will simply discard the incoming response. The corresponding DNS transaction MUST
Servers that receive STOP_SENDING act in accordance with Section 3.5
of RFC 9000
. Servers SHOULD NOT
continue processing a DNS transaction if they receive a STOP_SENDING.
impose implementation limits on the total number or rate of cancellation requests. If limits are encountered, servers MAY
close the connection. In this case, servers wanting to help client debugging MAY
use the error code DOQ_EXCESSIVE_LOAD. There is always a trade-off between helping good faith clients debug issues and allowing denial-of-service attackers to test server defenses; depending on circumstances servers might very well choose to send different error codes.
Note that this mechanism provides a way for secondaries to cancel a single zone transfer occurring on a given stream without having to close the QUIC connection.
Servers MUST NOT
continue processing a DNS transaction if they receive a RESET_STREAM request from the client before the client indicates the STREAM FIN. The server MUST
issue a RESET_STREAM to indicate that the transaction is abandoned unless:
it has already done so for another reason or
it has already both sent the response and indicated the STREAM FIN.
Servers normally complete transactions by sending a DNS response (or responses) on the transaction's stream, including cases where the DNS response indicates a DNS error. For example, a client SHOULD
be notified of a Server Failure (SERVFAIL, [RFC 1035
]) through a response with the Response Code set to SERVFAIL.
If a server is incapable of sending a DNS response due to an internal error, it SHOULD
issue a QUIC RESET_STREAM frame. The error code SHOULD
be set to DOQ_INTERNAL_ERROR. The corresponding DNS transaction MUST
be abandoned. Clients MAY
limit the number of unsolicited QUIC RESET_STREAM frames received on a connection before choosing to close the connection.
Note that this mechanism provides a way for primaries to abort a single zone transfer occurring on a given stream without having to close the QUIC connection.
Other error scenarios can occur due to malformed, incomplete, or unexpected messages during a transaction. These include (but are not limited to):
a client or server receives a message with a non-zero Message ID
a client or server receives a STREAM FIN before receiving all the bytes for a message indicated in the 2-octet length field
a client receives a STREAM FIN before receiving all the expected responses
a server receives more than one query on a stream
a client receives a different number of responses on a stream than expected (e.g., multiple responses to a query for an A record)
a client receives a STOP_SENDING request
the client or server does not indicate the expected STREAM FIN after sending requests or responses (see Section 4.2)
an implementation receives a message containing the edns-tcp-keepalive EDNS(0) Option [RFC 7828] (see Section 5.5.2)
a client or a server attempts to open a unidirectional QUIC stream
a server attempts to open a server-initiated bidirectional QUIC stream
a server receives a "replayable" transaction in 0-RTT data (for servers not willing to handle this case, see Section 4.5)
If a peer encounters such an error condition, it is considered a fatal error. It SHOULD
forcibly abort the connection using QUIC's CONNECTION_CLOSE mechanism and SHOULD
use the DoQ error code DOQ_PROTOCOL_ERROR. In some cases, it MAY
instead silently abandon the connection, which uses fewer of the local resources but makes debugging at the offending node more difficult.
It is noted that the restrictions on use of the above EDNS(0) option has implications for proxying messages from TCP/DoT/DoH over DoQ.
This specification describes specific error codes in Sections [4.3.1
], and [4.3.3
]. These error codes are meant to facilitate investigation of failures and other incidents. New error codes may be defined in future versions of DoQ or registered as specified in Section 8.4
Because new error codes can be defined without negotiation, use of an error code in an unexpected context or receipt of an unknown error code MUST
be treated as equivalent to DOQ_UNSPECIFIED_ERROR.
wish to test the support for the error code extension mechanism by using error codes not listed in this document, or they MAY
of RFC 9000
, the QUIC transport specification, specifies that connections can be closed in three ways:
Clients and servers implementing DoQ SHOULD
negotiate use of the idle timeout. Closing on idle timeout is done without any packet exchange, which minimizes protocol overhead. Per Section 10.1
of RFC 9000
, the QUIC transport specification, the effective value of the idle timeout is computed as the minimum of the values advertised by the two endpoints. Practical considerations on setting the idle timeout are discussed in Section 5.5.2
monitor the idle time incurred on their connection to the server, defined by the time spent since the last packet from the server has been received. When a client prepares to send a new DNS query to the server, it SHOULD
check whether the idle time is sufficiently lower than the idle timer. If it is, the client SHOULD
send the DNS query over the existing connection. If not, the client SHOULD
establish a new connection and send the query over that connection.
discard their connections to the server before the idle timeout expires. A client that has outstanding queries SHOULD
close the connection explicitly using QUIC's CONNECTION_CLOSE mechanism and the DoQ error code DOQ_NO_ERROR.
Clients and servers MAY
close the connection for a variety of other reasons, indicated using QUIC's CONNECTION_CLOSE. Client and servers that send packets over a connection discarded by their peer might receive a stateless reset indication. If a connection fails, all the in-progress transactions on that connection MUST
A client MAY
take advantage of the session resumption and 0-RTT mechanisms supported by QUIC transport [RFC 9000
] and QUIC TLS [RFC 9001
] if the server supports them. Clients SHOULD
consider potential privacy issues associated with session resumption before deciding to use this mechanism and specifically evaluate the trade-offs presented in the various sections of this document. The privacy issues are detailed in Sections [7.1
] and [7.2
], and the implementation considerations are discussed in Section 5.5.3
The 0-RTT mechanism MUST NOT
be used to send DNS requests that are not "replayable" transactions. In this specification, only transactions that have an OPCODE of QUERY or NOTIFY are considered replayable; therefore, other OPCODES MUST NOT
be sent in 0-RTT data. See Appendix A
for a detailed discussion of why NOTIFY is included here.
support session resumption, and MAY
do that with or without supporting 0-RTT, using the mechanisms described in Section 4.6.1
of RFC 9001
. Servers supporting 0-RTT MUST NOT
immediately process non-replayable transactions received in 0-RTT data but instead MUST
adopt one of the following behaviors:
Queue the offending transaction and only process it after the QUIC handshake has been completed, as defined in Section 4.1.1 of RFC 9001.
Reply to the offending transaction with a response code REFUSED and an Extended DNS Error Code (EDE) "Too Early" using the extended RCODE mechanisms defined in [RFC 6891] and the extended DNS errors defined in [RFC 8914]; see Section 8.3.
Close the connection with the error code DOQ_PROTOCOL_ERROR.
DoQ queries and responses are sent on QUIC streams, which in theory can carry up to 262
bytes. However, DNS messages are restricted in practice to a maximum size of 65535 bytes. This maximum size is enforced by the use of a 2-octet message length field in DNS over TCP [RFC 1035
] and DoT [RFC 7858
], and by the definition of the "application/dns-message" for DoH [RFC 8484
]. DoQ enforces the same restriction.
The Extension Mechanisms for DNS (EDNS(0)) [RFC 6891
] allow peers to specify the UDP message size. This parameter is ignored by DoQ. DoQ implementations always assume that the maximum message size is 65535 bytes.