accepted_payload_size is both the EDNS UDP advertisement and the
response size limit. A complete stream response larger than this value
is therefore discarded even though DNS stream framing can carry it. It
also makes it impossible to advertise a conservative UDP size while
accepting the complete response after a transport switch.
The stream code already rejects messages above the DNS protocol limit
and buffers the message before the resolver checks its size. Accepting
up to DNS_MAX_MSG_SIZE in the resolver therefore does not increase the
stream allocation.
Keep accepted_payload_size as the UDP advertisement and receive limit,
and use the protocol maximum for stream responses. Configurations that
used it to reject large stream responses will now accept those valid
messages.
---
doc/configuration.txt | 10 +++++-----
include/haproxy/resolvers-t.h | 2 +-
src/resolvers.c | 7 +++++--
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index fa9b418f4..26e930f4b 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -20377,17 +20377,17 @@ resolvers <resolvers id>
A resolvers section accept the following parameters:
accepted_payload_size <nb>
- Defines the maximum payload size accepted by HAProxy and announced to all the
- name servers configured in this resolvers section.
+ Defines the maximum UDP payload size accepted by HAProxy and announced to all
+ the name servers configured in this resolvers section.
<nb> is in bytes. If not set, HAProxy announces 512. (minimal value defined
by RFC 6891)
Note: the maximum allowed value is 65535. Recommended value for UDP is
4096 and it is not recommended to exceed 8192 except if you are sure
that your system and network can handle this (over 65507 makes no sense
- since is the maximum UDP payload size). If you are using only TCP
- nameservers to handle huge DNS responses, you should put this value
- to the max: 65535.
+ since it is the maximum UDP payload size). DNS responses received over
a
+ stream transport are accepted up to the DNS protocol maximum of 65535
+ bytes regardless of this setting.
nameserver <name> <address>[:port] [param*]
Used to configure a nameserver. <name> of the nameserver should ne unique.
diff --git a/include/haproxy/resolvers-t.h b/include/haproxy/resolvers-t.h
index 4b7213a0a..cc923c851 100644
--- a/include/haproxy/resolvers-t.h
+++ b/include/haproxy/resolvers-t.h
@@ -142,7 +142,7 @@ struct resolv_response {
*/
struct resolvers {
__decl_thread(HA_SPINLOCK_T lock);
- unsigned int accepted_payload_size; /* maximum payload size we accept
for responses */
+ unsigned int accepted_payload_size; /* maximum UDP payload size we
announce and accept */
int nb_nameservers; /* total number of nameservers in a
resolvers section */
int resolve_retries; /* number of retries before giving
up */
struct { /* time to: */
diff --git a/src/resolvers.c b/src/resolvers.c
index c63a1f373..fb935d359 100644
--- a/src/resolvers.c
+++ b/src/resolvers.c
@@ -2332,12 +2332,15 @@ static int resolv_process_responses(struct
dns_nameserver *ns, enum dns_server_t
unsigned char *bufend;
int buflen, dns_resp;
int max_answer_records;
+ unsigned int max_payload_size;
unsigned short query_id;
struct eb32_node *eb;
struct resolv_requester *req;
int keep_answer_items;
resolvers = ns->parent;
+ max_payload_size = dns_server_type_is_stream(type) ?
+ DNS_MAX_MSG_SIZE : resolvers->accepted_payload_size;
enter_resolver_code();
HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
@@ -2349,7 +2352,7 @@ static int resolv_process_responses(struct dns_nameserver
*ns, enum dns_server_t
break;
/* message too big */
- if (buflen > resolvers->accepted_payload_size) {
+ if (buflen > max_payload_size) {
ns->counters->app.resolver.too_big++;
continue;
}
@@ -2377,7 +2380,7 @@ static int resolv_process_responses(struct dns_nameserver
*ns, enum dns_server_t
/* number of responses received */
res->nb_responses++;
- max_answer_records = (resolvers->accepted_payload_size -
DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE;
+ max_answer_records = (max_payload_size - DNS_HEADER_SIZE) /
DNS_MIN_RECORD_SIZE;
dns_resp = resolv_validate_dns_response(buf, bufend, res,
max_answer_records);
switch (dns_resp) {
--
2.55.0