From 2514f41adee8b2f62b3c8a7035d90e3e0975fe45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 15 Feb 2022 14:41:15 +0100 Subject: [PATCH] Reset the TCP connection when garbage is received When invalid DNS message is received, there was a handling mechanism for DoH that would be called to return proper HTTP response. Reuse this mechanism and reset the TCP connection when the client is blackholed, DNS message is completely bogus or the ns_client receives response instead of query. (cherry picked from commit 4716c56ebb4e537845fb4753cba004f5b01923c6) --- lib/isc/netmgr/netmgr-int.h | 6 +++++ lib/isc/netmgr/netmgr.c | 54 +++++++++++++++++++++++++------------ lib/ns/client.c | 7 ++++- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 188d90340e..4f8db118ea 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -1247,6 +1247,12 @@ isc__nmsocket_shutdown(isc_nmsocket_t *sock); * callbacks. */ +void +isc__nmsocket_reset(isc_nmsocket_t *sock); +/*%< + * Reset and close the socket. + */ + bool isc__nmsocket_active(isc_nmsocket_t *sock); /*%< diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index ddcfe23276..409838befd 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1835,9 +1835,6 @@ isc__nmhandle_detach(isc_nmhandle_t **handlep FLARG) { } } -void -isc__nmsocket_shutdown(isc_nmsocket_t *sock); - static void nmhandle_detach_cb(isc_nmhandle_t **handlep FLARG) { isc_nmsocket_t *sock = NULL; @@ -2085,11 +2082,7 @@ isc__nmsocket_writetimeout_cb(uv_timer_t *timer) { int r = uv_timer_stop(&sock->write_timer); UV_RUNTIME_CHECK(uv_timer_stop, r); - /* The shutdown will be handled in the respective close functions */ - r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL); - UV_RUNTIME_CHECK(uv_tcp_close_reset, r); - - isc__nmsocket_shutdown(sock); + isc__nmsocket_reset(sock); } void @@ -2902,6 +2895,32 @@ isc__nm_async_detach(isc__networker_t *worker, isc__netievent_t *ev0) { nmhandle_detach_cb(&ievent->handle FLARG_PASS); } +void +isc__nmsocket_reset(isc_nmsocket_t *sock) { + REQUIRE(VALID_NMSOCK(sock)); + + switch (sock->type) { + case isc_nm_tcpdnssocket: + case isc_nm_tlsdnssocket: + REQUIRE(sock->parent == NULL); + break; + default: + INSIST(0); + ISC_UNREACHABLE(); + break; + } + + if (!uv_is_closing(&sock->uv_handle.handle)) { + /* + * The real shutdown will be handled in the respective + * close functions. + */ + int r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL); + UV_RUNTIME_CHECK(uv_tcp_close_reset, r); + } + isc__nmsocket_shutdown(sock); +} + void isc__nmsocket_shutdown(isc_nmsocket_t *sock) { REQUIRE(VALID_NMSOCK(sock)); @@ -3467,25 +3486,26 @@ isc_nm_sequential(isc_nmhandle_t *handle) { void isc_nm_bad_request(isc_nmhandle_t *handle) { - isc_nmsocket_t *sock; + isc_nmsocket_t *sock = NULL; REQUIRE(VALID_NMHANDLE(handle)); REQUIRE(VALID_NMSOCK(handle->sock)); sock = handle->sock; + switch (sock->type) { + case isc_nm_udpsocket: + return; + case isc_nm_tcpdnssocket: + case isc_nm_tlsdnssocket: + REQUIRE(sock->parent == NULL); + isc__nmsocket_reset(sock); + return; #if HAVE_LIBNGHTTP2 case isc_nm_httpsocket: isc__nm_http_bad_request(handle); - break; -#endif /* HAVE_LIBNGHTTP2 */ - - case isc_nm_udpsocket: - case isc_nm_tcpdnssocket: - case isc_nm_tlsdnssocket: return; - break; - +#endif /* HAVE_LIBNGHTTP2 */ case isc_nm_tcpsocket: #if HAVE_LIBNGHTTP2 case isc_nm_tlssocket: diff --git a/lib/ns/client.c b/lib/ns/client.c index e48eb56322..214c83fedf 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -1822,6 +1822,9 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult, * There isn't enough header to determine whether * this was a request or a response. Drop it. */ + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), + "dropped request: invalid message header"); isc_nm_bad_request(handle); return; } @@ -1838,7 +1841,9 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult, * If it's a TCP response, discard it here. */ if ((flags & DNS_MESSAGEFLAG_QR) != 0) { - CTRACE("unexpected response"); + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), + "dropped request: unexpected response"); isc_nm_bad_request(handle); return; }