Prevent query loops for misbehaving servers
If a TCP connection fails while attempting to send a query to a server, the fetch context will be restarted without marking the target server as a bad one. If this happens for a server which: - was already marked with the DNS_FETCHOPT_EDNS512 flag, - responds to EDNS queries with the UDP payload size set to 512 bytes, - does not send response packets larger than 512 bytes, and the response for the query being sent is larger than 512 byes, then named will pointlessly alternate between sending UDP queries with EDNS UDP payload size set to 512 bytes (which are responded to with truncated answers) and TCP connections until the fetch context retry limit is reached. Prevent such query loops by marking the server as bad for a given fetch context if the advertised EDNS UDP payload size for that server gets reduced to 512 bytes and it is impossible to reach it using TCP.
This commit is contained in:
@@ -2956,6 +2956,19 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
* No route to remote.
|
||||
*/
|
||||
isc_socket_detach(&query->tcpsocket);
|
||||
/*
|
||||
* Do not query this server again in this fetch context
|
||||
* if we already tried reducing the advertised EDNS UDP
|
||||
* payload size to 512 bytes and the server is
|
||||
* unavailable over TCP. This prevents query loops
|
||||
* lasting until the fetch context restart limit is
|
||||
* reached when attempting to get answers whose size
|
||||
* exceeds 512 bytes from broken servers.
|
||||
*/
|
||||
if ((query->options & DNS_FETCHOPT_EDNS512) != 0) {
|
||||
add_bad(fctx, query->addrinfo, sevent->result,
|
||||
badns_unreachable);
|
||||
}
|
||||
fctx_cancelquery(&query, NULL, NULL,
|
||||
true, false);
|
||||
retry = true;
|
||||
|
||||
Reference in New Issue
Block a user