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 4716c56ebb)
This commit is contained in:
Ondřej Surý
2022-02-15 14:41:15 +01:00
parent d7bcb0b5b7
commit 2514f41ade
3 changed files with 49 additions and 18 deletions

View File

@@ -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);
/*%<

View File

@@ -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:

View File

@@ -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;
}