From: Alan T. DeKok Date: Thu, 7 Dec 2023 11:46:31 +0000 (-0500) Subject: add proxy_dedup_window X-Git-Tag: release_3_2_4~107 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c27585db43ae5d2322dc792fc664e4a49699453;p=thirdparty%2Ffreeradius-server.git add proxy_dedup_window which controls how the server drops aggressive retransmissions from a misbehaving NAS --- diff --git a/raddb/radiusd.conf.in b/raddb/radiusd.conf.in index 5a521cb4f48..12fac7abd5e 100644 --- a/raddb/radiusd.conf.in +++ b/raddb/radiusd.conf.in @@ -269,6 +269,27 @@ hostname_lookups = no # #postauth_client_lost = no +# +# Some NASes will aggressively retransmit packets, and cause a DoS of +# the RADIUS infrastructure. They should follow he recommended +# retransmission behavior of RFC 5080 Section 2.2.2, but it seems +# that only (some) RADIUS servers follow that guidance. +# +# When a duplicate packet is received from the NAS, the server will +# see when the last retransmission was done. If it is within the +# "proxy_dedup_window", the retransmitted packet is dropped. +# +# i.e. There is zero benefit to sending the same RADIUS packet +# multiple times in one second. There is, in fact, serious harm +# in doing so. Aggressive retransmissions can result in network +# congestion, and ultimately failure of the RADIUS infrastructure. +# +# This behavior *cannot* be disabled. +# +# Allowed values here are 1..10. Only integers are supported. +# +#proxy_dedup_window = 1 + # # Logging section. The various "log_*" configuration items # will eventually be moved here. diff --git a/src/include/radiusd.h b/src/include/radiusd.h index 594a6bde872..982f2124c62 100644 --- a/src/include/radiusd.h +++ b/src/include/radiusd.h @@ -141,6 +141,8 @@ typedef struct main_config { uint32_t cleanup_delay; //!< How long before cleaning up cached responses. uint32_t max_requests; + uint32_t proxy_dedup_window; //!< suppress duplicate retransmitssions from a NAS + bool postauth_client_lost; //!< Whether to run Post-Auth-Type Client-Lost section uint32_t debug_level; diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index 227ae4acfde..9c268a1ce08 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -195,6 +195,7 @@ static const CONF_PARSER server_config[] = { { "panic_action", FR_CONF_POINTER(PW_TYPE_STRING, &main_config.panic_action), NULL}, { "hostname_lookups", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &fr_dns_lookups), "no" }, { "max_request_time", FR_CONF_POINTER(PW_TYPE_INTEGER, &main_config.max_request_time), STRINGIFY(MAX_REQUEST_TIME) }, + { "proxy_dedup_window", FR_CONF_POINTER(PW_TYPE_INTEGER, &main_config.proxy_dedup_window), "1" }, { "cleanup_delay", FR_CONF_POINTER(PW_TYPE_INTEGER, &main_config.cleanup_delay), STRINGIFY(CLEANUP_DELAY) }, { "max_requests", FR_CONF_POINTER(PW_TYPE_INTEGER, &main_config.max_requests), STRINGIFY(MAX_REQUESTS) }, { "postauth_client_lost", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.postauth_client_lost), "no" }, @@ -1144,6 +1145,10 @@ do {\ if ((main_config.reject_delay.tv_sec != 0) || (main_config.reject_delay.tv_usec != 0)) { FR_TIMEVAL_BOUND_CHECK("reject_delay", &main_config.reject_delay, >=, 1, 0); } + + FR_INTEGER_BOUND_CHECK("proxy_dedup_window", main_config.proxy_dedup_window, <=, 10); + FR_INTEGER_BOUND_CHECK("proxy_dedup_window", main_config.proxy_dedup_window, >=, 1); + FR_TIMEVAL_BOUND_CHECK("reject_delay", &main_config.reject_delay, <=, 10, 0); FR_INTEGER_BOUND_CHECK("cleanup_delay", main_config.cleanup_delay, <=, 30); diff --git a/src/main/process.c b/src/main/process.c index ff3263bbe76..34e9866dd71 100644 --- a/src/main/process.c +++ b/src/main/process.c @@ -4363,7 +4363,7 @@ static void proxy_wait_for_reply(REQUEST *request, int action) * and should be suppressed by the proxy. */ when = request->proxy->timestamp; - when.tv_sec++; + when.tv_sec += main_config.proxy_dedup_window; if (timercmp(&now, &when, <)) { DEBUG2("Suppressing duplicate proxied request (too fast) to home server %s port %d - ID: %d",