From ba1cadf14aba037624a99035df57f04ac37fb24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 29 Nov 2021 09:59:33 +0100 Subject: [PATCH] Tear down the TCP connection on too many unexpected DNS messages When the outgoing TCP dispatch times-out active response, we might still receive the answer during the lifetime of the connection. Previously, we would just ignore any non-matching DNS answers, which would allow the server to feed us with otherwise valid DNS answer and keep the connection open. Add a counter for timed-out DNS queries over TCP and tear down the whole TCP connection if we receive unexpected number of DNS answers. --- lib/dns/dispatch.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 338a569c74..8c4cd2c91d 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -134,6 +134,8 @@ struct dns_dispatch { unsigned int requests; /*%< how many requests we have */ unsigned int tcpbuffers; /*%< allocated buffers */ + + unsigned int timedout; }; #define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ') @@ -644,8 +646,13 @@ tcp_recv_success(dns_dispatch_t *disp, isc_region_t *region, dns_qid_t *qid, if (resp != NULL) { dispentry_attach(resp, &(dns_dispentry_t *){ NULL }); *respp = resp; - } else { + } else if (disp->timedout > 0) { + /* There was active query that timed-out before */ + disp->timedout--; result = ISC_R_NOTFOUND; + } else { + /* We are not expecting this DNS message */ + result = ISC_R_UNEXPECTED; } dispatch_log(disp, LVL(90), "search for response in bucket %d: %s", bucket, isc_result_totext(result)); @@ -665,6 +672,8 @@ tcp_recv_timeout(dns_dispatch_t *disp, dns_dispentry_t **respp) { ISC_LIST_UNLINK(disp->active, resp, alink); ISC_LIST_APPEND(disp->active, resp, alink); + disp->timedout++; + *respp = resp; return (ISC_R_TIMEDOUT); }