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).