This section describes measures that systems and applications can take to optimize performance over TCP and to protect themselves from TCP-based resource exhaustion and attacks.
Resolvers and other DNS clients should be aware that some servers might not be reachable over TCP. For this reason, clients
MAY track and limit the number of TCP connections and connection attempts to a single server. Reachability problems can be caused by network elements close to the server, close to the client, or anywhere along the path between them. Mobile clients that cache connection failures
MAY do so on a per-network basis or
MAY clear such a cache upon change of network.
Additionally, DNS clients
MAY enforce a short timeout on unestablished connections rather than rely on the host operating system's TCP connection timeout, which is often around 60-120 seconds (i.e., due to an initial retransmission timeout of 1 second, the exponential back-off rules of [
RFC 6298], and a limit of six retries as is the default in Linux).
The SYN flooding attack is a denial-of-service method affecting hosts that run TCP server processes [
RFC 4987]. This attack can be very effective if not mitigated. One of the most effective mitigation techniques is SYN cookies, described in
Section 3.6 of
RFC 4987, which allows the server to avoid allocating any state until the successful completion of the three-way handshake.
Services not intended for use by the public Internet, such as most recursive name servers,
SHOULD be protected with access controls. Ideally, these controls are placed in the network, well before any unwanted TCP packets can reach the DNS server host or application. If this is not possible, the controls can be placed in the application itself. In some situations (e.g., attacks), it may be necessary to deploy access controls for DNS services that should otherwise be globally reachable. See also [
RFC 5358].
The FreeBSD and NetBSD operating systems have an "accept filter" feature ([
accept_filter]) that postpones delivery of TCP connections to applications until a complete, valid request has been received. The dns_accf(9) filter ensures that a valid DNS message is received. If not, the bogus connection never reaches the application. The Linux TCP_DEFER_ACCEPT feature, while more limited in scope, can provide some of the same benefits as the BSD accept filter feature. These features are implemented as low-level socket options and are not activated automatically. If applications wish to use these features, they need to make specific calls to set the right options, and administrators may also need to configure the applications to appropriately use the features.
Per [
RFC 7766], applications and administrators are advised to remember that TCP
MAY be used before sending any UDP queries. Networks and applications
MUST NOT be configured to refuse TCP queries that were not preceded by a UDP query.
TCP Fast Open (TFO) [
RFC 7413] allows TCP clients to shorten the handshake for subsequent connections to the same server. TFO saves one round-trip time in the connection setup. DNS servers
SHOULD enable TFO when possible. Furthermore, DNS servers clustered behind a single service address (e.g., anycast or load balancing)
SHOULD either use the same TFO server key on all instances or disable TFO for all members of the cluster.
DNS clients
MAY also enable TFO. At the time of this writing, it is not implemented or is disabled by default on some operating systems. [
WIKIPEDIA_TFO] describes applications and operating systems that support TFO.
Since host memory for TCP state is a finite resource, DNS clients and servers
SHOULD actively manage their connections. Applications that do not actively manage their connections can encounter resource exhaustion leading to denial of service. For DNS, as in other protocols, there is a trade-off between keeping connections open for potential future use and the need to free up resources for new connections that will arrive.
Operators of DNS server software
SHOULD be aware that operating system and application vendors
MAY impose a limit on the total number of established connections. These limits may be designed to protect against DDoS attacks or performance degradation. Operators
SHOULD understand how to increase these limits if necessary and the consequences of doing so. Limits imposed by the application
SHOULD be lower than limits imposed by the operating system so that the application can apply its own policy to connection management, such as closing the oldest idle connections first.
DNS server software
MAY provide a configurable limit on the number of established connections per source IP address or subnet. This can be used to ensure that a single or small set of users cannot consume all TCP resources and deny service to other users. Note, however, that if this limit is enabled, it possibly limits client performance while leaving some TCP resources unutilized. Operators
SHOULD be aware of these trade-offs and ensure this limit, if configured, is set appropriately based on the number and diversity of their users and whether users connect from unique IP addresses or through a shared Network Address Translator (NAT) [
RFC 3022].
DNS server software
SHOULD provide a configurable timeout for idle TCP connections. This can be used to free up resources for new connections and to ensure that idle connections are eventually closed. At the same time, it possibly limits client performance while leaving some TCP resources unutilized. For very busy name servers, this might be set to a low value, such as a few seconds. For less busy servers, it might be set to a higher value, such as tens of seconds. DNS clients and servers
SHOULD signal their timeout values using the edns-tcp-keepalive EDNS(0) option [
RFC 7828].
DNS server software
MAY provide a configurable limit on the number of transactions per TCP connection. This can help protect against unfair connection use (e.g., not releasing connection slots to other clients) and network evasion attacks.
Similarly, DNS server software
MAY provide a configurable limit on the total duration of a TCP connection. This can help protect against unfair connection use, slow read attacks, and network evasion attacks.
Since clients may not be aware of server-imposed limits, clients utilizing TCP for DNS need to always be prepared to re-establish connections or otherwise retry outstanding queries.
The TCP peer that initiates a connection close retains the socket in the TIME_WAIT state for some amount of time, possibly a few minutes. It is generally preferable for clients to initiate the close of a TCP connection so that busy servers do not accumulate many sockets in the TIME_WAIT state, which can cause performance problems or even denial of service. The edns-tcp-keepalive EDNS(0) option [
RFC 7828] can be used to encourage clients to close connections.
On systems where large numbers of sockets in TIME_WAIT are observed (as either a client or a server) and are affecting an application's performance, it may be tempting to tune local TCP parameters. For example, the Linux kernel has a "sysctl" parameter named net.ipv4.tcp_tw_reuse, which allows connections in the TIME_WAIT state to be reused in specific circumstances. Note, however, that this affects only outgoing (client) connections and has no impact on servers. In most cases, it is
NOT RECOMMENDED to change parameters related to the TIME_WAIT state. It should only be done by those with detailed knowledge of both TCP and the affected application.
DNS messages may be sent over TLS to provide privacy between stubs and recursive resolvers. [
RFC 7858] is a Standards Track document describing how this works. Although DNS over TLS utilizes TCP port 853 instead of port 53, this document applies equally well to DNS over TLS. Note, however, that DNS over TLS is only defined between stubs and recursives at the time of this writing.
The use of TLS places even stronger operational burdens on DNS clients and servers. Cryptographic functions for authentication and encryption require additional processing. Unoptimized connection setup with TLS 1.3 [
RFC 8446] takes one additional round trip compared to TCP. Connection setup times can be reduced with TCP Fast Open and TLS False Start [
RFC 7918] for TLS 1.2. TLS 1.3 session resumption does not reduce round-trip latency because no application profile for use of TLS 0-RTT data with DNS has been published at the time of this writing. However, TLS session resumption can reduce the number of cryptographic operations, and in TLS 1.2, session resumption does reduce the number of additional round trips from two to one.
A survey of features and defaults was conducted for popular open-source DNS server implementations at the time of writing. This section documents those defaults and makes recommendations for configurable limits that can be used in the absence of any other information. Any recommended values in this document are only intended as a starting point for administrators that are unsure of what sorts of limits might be reasonable. Operators
SHOULD use application-specific monitoring, system logs, and system monitoring tools to gauge whether their service is operating within or exceeding these limits and adjust accordingly.
Most open-source DNS server implementations provide a configurable limit on the total number of established connections. Default values range from 20 to 150. In most cases, where the majority of queries take place over UDP, 150 is a reasonable limit. For services or environments where most queries take place over TCP or TLS, 5000 is a more appropriate limit.
Only some open-source implementations provide a way to limit the number of connections per source IP address or subnet, but the default is to have no limit. For environments or situations where it may be necessary to enable this limit, 25 connections per source IP address is a reasonable starting point. The limit should be increased when aggregated by subnet or for services where most queries take place over TCP or TLS.
Most open-source implementations provide a configurable idle timeout on connections. Default values range from 2 to 30 seconds. In most cases, 10 seconds is a reasonable default for this limit. Longer timeouts improve connection reuse, but busy servers may need to use a lower limit.
Only some open-source implementations provide a way to limit the number of transactions per connection, but the default is to have no limit. This document does not offer advice on particular values for such a limit.
Only some open-source implementations provide a way to limit the duration of connection, but the default is to have no limit. This document does not offer advice on particular values for such a limit.