From: Manu Nicolas Date: Tue, 1 Sep 2026 10:44:50 +0000 (+0000) Subject: MEDIUM: resolvers: accept full-size DNS messages over streams X-Git-Tag: v3.5-dev6~20 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=9909d634c5f7113c959e882ed336854ba86e6dd2;p=haproxy.git MEDIUM: resolvers: accept full-size DNS messages over streams 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. --- 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 A resolvers section accept the following parameters: accepted_payload_size - 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. 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
[:port] [param*] Used to configure a nameserver. 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 17d21d1f4..e9d97a67a 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) {