diff --git a/command/agent/dns.go b/command/agent/dns.go
index cebbf4382c..20a5430853 100644
--- a/command/agent/dns.go
+++ b/command/agent/dns.go
@@ -17,7 +17,11 @@ import (
)
const (
- maxUDPAnswerLimit = 8 // For UDP only
+ // UDP can fit ~25 A records in a 512B response, and ~14 AAAA
+ // records. Limit further to prevent unintentional configuration
+ // abuse that would have a negative effect on application response
+ // times.
+ maxUDPAnswerLimit = 8
maxRecurseRecords = 5
)
@@ -488,15 +492,16 @@ func (d *DNSServer) formatNodeRecord(node *structs.Node, addr, qName string, qTy
return records
}
-// trimAnswers makes sure a UDP response is not longer than allowed by RFC 1035.
-// We first enforce an arbitrary limit, and then make sure the response doesn't
-// exceed 512 bytes.
-func trimAnswers(resp *dns.Msg) (trimmed bool) {
+// trimUDPAnswers makes sure a UDP response is not longer than allowed by RFC
+// 1035. Enforce an arbitrary limit that can be further ratcheted down by
+// config, and then make sure the response doesn't exceed 512 bytes.
+func trimUDPAnswers(config *DNSConfig, resp *dns.Msg) (trimmed bool) {
numAnswers := len(resp.Answer)
// This cuts UDP responses to a useful but limited number of responses.
- if numAnswers > maxServiceResponses {
- resp.Answer = resp.Answer[:maxServiceResponses]
+ maxAnswers := lib.MinInt(maxUDPAnswerLimit, config.UDPAnswerLimit)
+ if numAnswers > maxAnswers {
+ resp.Answer = resp.Answer[:maxAnswers]
}
// This enforces the hard limit of 512 bytes per the RFC.
@@ -504,7 +509,7 @@ func trimAnswers(resp *dns.Msg) (trimmed bool) {
resp.Answer = resp.Answer[:len(resp.Answer)-1]
}
- return len(resp.Answer) < numAnswers
+ return len(resp.Answer) < maxAnswers
}
// serviceLookup is used to handle a service query
@@ -568,7 +573,7 @@ RPC:
// If the network is not TCP, restrict the number of responses
if network != "tcp" {
- wasTrimmed := trimAnswers(resp)
+ wasTrimmed := trimUDPAnswers(d.config, resp)
// Flag that there are more records to return in the UDP response
if wasTrimmed && d.config.EnableTruncate {
@@ -663,7 +668,7 @@ RPC:
// If the network is not TCP, restrict the number of responses.
if network != "tcp" {
- wasTrimmed := trimAnswers(resp)
+ wasTrimmed := trimUDPAnswers(d.config, resp)
// Flag that there are more records to return in the UDP response
if wasTrimmed && d.config.EnableTruncate {
diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown
index ffba6126c0..112dbf8a4d 100644
--- a/website/source/docs/agent/options.html.markdown
+++ b/website/source/docs/agent/options.html.markdown
@@ -507,28 +507,18 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
service addresses regardless of the health of the service.
* `udp_answer_limit` - Artificially limit the
- number of resource records contained in the answer section of a UDP-based
- DNS response. The default number of resource records returned is `3`. In
+ href="#udp_answer_limit">`udp_answer_limit` - Limit the number of
+ resource records contained in the answer section of a UDP-based DNS
+ response. The default number of resource records returned is `3`. In
environments where
[RFC 3484 Section 6](https://tools.ietf.org/html/rfc3484#section-6) Rule 9
- is implemented and enforced, clients may need to set this value to `1` to
+ is implemented and enforced (i.e. DNS answers are always sorted and
+ therefore never random), clients may need to set this value to `1` to
preserve randomized DNS round-robin (note:
[https://tools.ietf.org/html/rfc3484](RFC 3484) has been obsoleted by
- [RFC 6724](https://tools.ietf.org/html/rfc6724) so it should be uncommon to
- need to change this value).
-
- * `udp_answer_limit` - Artificially limit the
- number of resource records contained in the answer section of a UDP-based
- DNS response. The default number of resource records returned is `3`. In
- environments where
- [RFC 3484 Section 6](https://tools.ietf.org/html/rfc3484#section-6) Rule 9
- is implemented and enforced, clients may need to set this value to `1` to
- preserve randomized DNS round-robin (note:
- [https://tools.ietf.org/html/rfc3484](RFC 3484) has been obsoleted by
- [RFC 6724](https://tools.ietf.org/html/rfc6724) so it should be uncommon to
- need to change this value).
+ [RFC 6724](https://tools.ietf.org/html/rfc6724) and as a result it should
+ be increasingly uncommon to need to change this value with modern
+ resolvers).
* `domain` Equivalent to the
[`-domain` command-line flag](#_domain).