Trim UDP responses per configuration

This commit is contained in:
Sean Chittenden 2016-03-29 19:27:02 -07:00
parent 4b5674bee3
commit c5c8daf07a
2 changed files with 23 additions and 28 deletions

View File

@ -17,7 +17,11 @@ import (
) )
const ( 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 maxRecurseRecords = 5
) )
@ -488,15 +492,16 @@ func (d *DNSServer) formatNodeRecord(node *structs.Node, addr, qName string, qTy
return records return records
} }
// trimAnswers makes sure a UDP response is not longer than allowed by RFC 1035. // trimUDPAnswers makes sure a UDP response is not longer than allowed by RFC
// We first enforce an arbitrary limit, and then make sure the response doesn't // 1035. Enforce an arbitrary limit that can be further ratcheted down by
// exceed 512 bytes. // config, and then make sure the response doesn't exceed 512 bytes.
func trimAnswers(resp *dns.Msg) (trimmed bool) { func trimUDPAnswers(config *DNSConfig, resp *dns.Msg) (trimmed bool) {
numAnswers := len(resp.Answer) numAnswers := len(resp.Answer)
// This cuts UDP responses to a useful but limited number of responses. // This cuts UDP responses to a useful but limited number of responses.
if numAnswers > maxServiceResponses { maxAnswers := lib.MinInt(maxUDPAnswerLimit, config.UDPAnswerLimit)
resp.Answer = resp.Answer[:maxServiceResponses] if numAnswers > maxAnswers {
resp.Answer = resp.Answer[:maxAnswers]
} }
// This enforces the hard limit of 512 bytes per the RFC. // 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] 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 // 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 the network is not TCP, restrict the number of responses
if network != "tcp" { if network != "tcp" {
wasTrimmed := trimAnswers(resp) wasTrimmed := trimUDPAnswers(d.config, resp)
// Flag that there are more records to return in the UDP response // Flag that there are more records to return in the UDP response
if wasTrimmed && d.config.EnableTruncate { if wasTrimmed && d.config.EnableTruncate {
@ -663,7 +668,7 @@ RPC:
// If the network is not TCP, restrict the number of responses. // If the network is not TCP, restrict the number of responses.
if network != "tcp" { if network != "tcp" {
wasTrimmed := trimAnswers(resp) wasTrimmed := trimUDPAnswers(d.config, resp)
// Flag that there are more records to return in the UDP response // Flag that there are more records to return in the UDP response
if wasTrimmed && d.config.EnableTruncate { if wasTrimmed && d.config.EnableTruncate {

View File

@ -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. service addresses regardless of the health of the service.
* <a name="udp_answer_limit"></a><a * <a name="udp_answer_limit"></a><a
href="#udp_answer_limit">`udp_answer_limit`</a> - Artificially limit the href="#udp_answer_limit">`udp_answer_limit`</a> - Limit the number of
number of resource records contained in the answer section of a UDP-based resource records contained in the answer section of a UDP-based DNS
DNS response. The default number of resource records returned is `3`. In response. The default number of resource records returned is `3`. In
environments where environments where
[RFC 3484 Section 6](https://tools.ietf.org/html/rfc3484#section-6) Rule 9 [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: preserve randomized DNS round-robin (note:
[https://tools.ietf.org/html/rfc3484](RFC 3484) has been obsoleted by [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 [RFC 6724](https://tools.ietf.org/html/rfc6724) and as a result it should
need to change this value). be increasingly uncommon to need to change this value with modern
resolvers).
* <a name="udp_answer_limit"></a><a
href="#udp_answer_limit">`udp_answer_limit`</a> - 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).
* <a name="domain"></a><a href="#domain">`domain`</a> Equivalent to the * <a name="domain"></a><a href="#domain">`domain`</a> Equivalent to the
[`-domain` command-line flag](#_domain). [`-domain` command-line flag](#_domain).