]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Tear down the TCP connection on too many unexpected DNS messages
authorOndřej Surý <ondrej@sury.org>
Mon, 29 Nov 2021 08:59:33 +0000 (09:59 +0100)
committerEvan Hunt <each@isc.org>
Wed, 1 Dec 2021 19:45:55 +0000 (11:45 -0800)
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

index 338a569c74ce6eb5c3b8829a2c4d0c4ef8c714d7..8c4cd2c91d23a8cd425c8f2e51b4606c98e2dcf9 100644 (file)
@@ -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);
        }