Skip to content

Commit 7fa1f2c

Browse files
terryburtonalandekok
authored andcommitted
Preliminary mod_proxy_rate_limit module
1 parent fbc5429 commit 7fa1f2c

File tree

6 files changed

+628
-2
lines changed

6 files changed

+628
-2
lines changed

raddb/all.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ LOCAL_SITES := $(addprefix raddb/sites-enabled/,$(DEFAULT_SITES))
1010
DEFAULT_MODULES := always attr_filter chap date \
1111
detail detail.log digest dynamic_clients eap \
1212
echo exec expiration expr files linelog logintime \
13-
mschap ntlm_auth pap passwd preprocess radutmp realm \
14-
replicate soh sradutmp totp unix unpack utf8
13+
mschap ntlm_auth pap passwd preprocess proxy_rate_limit \
14+
radutmp realm replicate soh sradutmp totp unix unpack utf8
1515

1616
ifneq "$(OPENSSL_LIBS)" ""
1717
DEFAULT_MODULE += dpsk
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# -*- text -*-
2+
#
3+
# $Id$
4+
5+
#
6+
# This module performs rate limiting on proxied packets.
7+
#
8+
# In some cases, a home server does not delay Access-Reject packets.
9+
# Badly behaved end-user devices may then try to authenticate many
10+
# hundreds of times a second. This behavior is effectively a denial
11+
# of service (DoS) attack on the RADIUS infastructure.
12+
#
13+
# This module tracks Access-Reject packets based on a key. If the
14+
# device is trying to authenticate too many times in quick
15+
# succession, the module will return a reject rather than proxying
16+
# the packet. These Access-Requests will not be proxied for a
17+
# configurable period of time, which is the "suppression period".
18+
#
19+
# Access-Reject responses from home servers for proxied requests are
20+
# store in a local tracking structure, keyed by username + supplicant
21+
# MAC. IDs are tracked to identify retransmission of the most recent
22+
# request. There should be few issues with lock contention, as the
23+
# tracking structure is designed carefully to avoid locks, or use
24+
# multiple distinct locks.
25+
#
26+
# Prior to proxying a request (in the pre-proxy section), the
27+
# tracking structure is queried. If an activate entry exists for the
28+
# device, then an Access-Reject will be sent and proxying will be
29+
# cancelled. Multiple requests arriving within the same second from a
30+
# device will cause the suppression period to the extended.
31+
#
32+
# When a request is proxied, if the reponse from the home server (in
33+
# the post-proxy section) is Access-Reject, then the device will be
34+
# added to the corresponding tracking table. If the device does not
35+
# quickly re-authenticate, then the tracking tavble entry is
36+
# discarded.
37+
#
38+
# However, if multiple requests arrive for the same device within the
39+
# same second, the module start rate-limiting requests as described
40+
# above.
41+
#
42+
43+
#
44+
# Update the "pre-proxy" section to list the "proxy_rate_limit" module:
45+
#
46+
# pre-proxy {
47+
# ...
48+
# proxy_rate_limit
49+
# ...
50+
# }
51+
#
52+
# And update the "post-proxy" section to list the "proxy_rate_limit" module:
53+
#
54+
# post-proxy {
55+
# ...
56+
# proxy_rate_limit
57+
# ...
58+
# }
59+
#
60+
61+
#
62+
# The module configuration.
63+
#
64+
proxy_rate_limit {
65+
#
66+
# The key used to track entries.
67+
#
68+
# For now, the key is not configurable, and is hard-coded to be the expansion below.
69+
#
70+
# key = "%{User-Name}%{Calling-Station-Id}
71+
72+
#
73+
# This limits the maximum number of entries which are
74+
# tracked. If the table becomes full, then older entries
75+
# will be evicted to make room for new entries.
76+
#
77+
max_entries = 2048
78+
79+
#
80+
# The idle timeout period, or lifetime of entries. If we do
81+
# not see packets for a device within this time limit, then
82+
# the entry is expired.
83+
#
84+
idle_timeout = 10
85+
}

raddb/sites-available/default

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,24 @@ post-auth {
11051105
# Only a few modules currently have this method.
11061106
#
11071107
pre-proxy {
1108+
# Some supplicants will aggressively retry after an Access-Reject,
1109+
# contrary to standards. You can avoid sending excessive load to home
1110+
# servers that based on recent history is likely to only result in
1111+
# further authentication failures by calling the proxy_rate_limit
1112+
# module here and in the post-proxy section.
1113+
#
1114+
# If a request is send too soon after a home server returned an
1115+
# Access-Reject, then instead of proxying a request a Access-Reject
1116+
# will be returned.
1117+
#
1118+
# The principle is to expend a small amount of resources at the edge
1119+
# (an in-memory cache of recent rejects for calling stations) to
1120+
# defend the limited processing and network resources at the core.
1121+
#
1122+
# The strategy can be tuned in the module configuration.
1123+
#
1124+
# proxy_rate_limit
1125+
11081126
# Before proxing the request add an Operator-Name attribute identifying
11091127
# if the operator-name is found for this client.
11101128
# No need to uncomment this if you have already enabled this in
@@ -1163,6 +1181,12 @@ post-proxy {
11631181
#
11641182
# eap
11651183

1184+
# If proxied requests are to be rate limited, then the
1185+
# proxy_rate_limit module must be called here to maintain a
1186+
# record of proxy responses.
1187+
#
1188+
# proxy_rate_limit
1189+
11661190
#
11671191
# If the server tries to proxy a request and fails, then the
11681192
# request is processed through the modules in this section.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
TARGETNAME := rlm_proxy_rate_limit
2+
3+
TARGET := $(TARGETNAME).a
4+
SOURCES := $(TARGETNAME).c

0 commit comments

Comments
 (0)