You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

142 lines
5.1 KiB

#!trydef ANTIFLOOD_RATE_WINDOW 2
#!trydef ANTIFLOOD_RATE_DENSITY 50
#!trydef ANTIFLOOD_RATE_EXPIRE 4
#!trydef ANTIFLOOD_FAILED_AUTH_WINDOW 300
#!trydef ANTIFLOOD_FAILED_AUTH_DENSITY 4
#!trydef ANTIFLOOD_FAILED_AUTH_USE_PORT 1
#!trydef ANTIFLOOD_FAILED_AUTH_ACTION 2
#!trydef ANTIFLOOD_RATE_LIMIT_ENABLED 1
#!trydef ANTIFLOOD_AUTH_LIMIT_ENABLED 1
#!trydef ANTIFLOOD_RATE_DROP 1
#!trydef ANTIFLOOD_CACHE_PERIOD 300
#!substdef "!ANTIFLOOD_SUBST_CACHE_PERIOD!$def(ANTIFLOOD_CACHE_PERIOD)!g"
######## Flood Prevention Hash Tables ########
modparam("htable", "htable", "antiflood=>size=16;autoexpire=ANTIFLOOD_SUBST_CACHE_PERIOD;initval=0")
######## Flood Prevention Module ########
loadmodule "pike.so"
modparam("pike", "sampling_time_unit", ANTIFLOOD_RATE_WINDOW)
modparam("pike", "reqs_density_per_unit", ANTIFLOOD_RATE_DENSITY)
modparam("pike", "remove_latency", ANTIFLOOD_RATE_EXPIRE)
kazoo.antiflood_failed_auth_use_port = ANTIFLOOD_FAILED_AUTH_USE_PORT descr "should we keep track of ip and port for auth failures"
kazoo.antiflood_failed_auth_action = ANTIFLOOD_FAILED_AUTH_ACTION descr "0 - log, 1 - drop, 2 - reply with 403"
kazoo.antiflood_rate_limit_enabled = ANTIFLOOD_RATE_LIMIT_ENABLED descr "antiflood rate limit enabled"
kazoo.antiflood_auth_limit_enabled = ANTIFLOOD_AUTH_LIMIT_ENABLED descr "antiflood auth limit enabled"
kazoo.antiflood_rate_drop = ANTIFLOOD_RATE_DROP descr "should we drop on rate limit"
route[ANTIFLOOD_LIMIT]
{
if($sel(cfg_get.kazoo.antiflood_rate_limit_enabled) == 1) {
route(ANTIFLOOD_RATE_LIMIT);
}
if($sel(cfg_get.kazoo.antiflood_auth_limit_enabled) == 1) {
route(ANTIFLOOD_AUTH_LIMIT);
}
}
route[ANTIFLOOD_RATE_LIMIT]
{
if (has_totag()
|| isflagset(FLAG_TRUSTED_SOURCE)
|| isflagset(FLAG_INTERNALLY_SOURCED)) {
return;
}
# use pike to control the rates
if (!pike_check_req()) {
if($sel(cfg_get.kazoo.antiflood_rate_drop) == 1) {
xlog("L_WARN", "$ci|end|dropping request from $fu due to rate of requests with source $si:$sp\n");
drop();
} else {
xlog("L_WARN", "$ci|antiflood|request from $fu exceeded rate of requests with source $si:$sp\n");
}
}
}
route[ANTIFLOOD_AUTH_LIMIT]
{
if (has_totag()
|| isflagset(FLAG_TRUSTED_SOURCE)
|| isflagset(FLAG_INTERNALLY_SOURCED)) {
return(1);
}
if (is_method("OPTIONS")) return(1);
$var(auth_key) = "";
if($sel(cfg_get.kazoo.antiflood_failed_auth_use_port) == 1) {
$var(auth_key) = $_s("$Au::$si::$sp");
} else {
$var(auth_key) = $_s("$Au::$si");
}
if ($Au != $null &&
$sht(antiflood=>$var(auth_key)::count) >= ANTIFLOOD_FAILED_AUTH_DENSITY
) {
$shtex(antiflood=>$var(auth_key)::count) = ANTIFLOOD_FAILED_AUTH_WINDOW;
$sht(antiflood=>$var(auth_key)::last) = $Ts;
if($sel(cfg_get.kazoo.antiflood_failed_auth_action) == 1) {
xlog("L_WARNING", "$ci|end|dropping request authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
drop();
} else if($sel(cfg_get.kazoo.antiflood_failed_auth_action) == 2) {
xlog("L_NOTICE", "$ci|end|authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
append_to_reply("Retry-After: 3600\r\n");
send_reply("403", "Forbidden");
exit;
} else {
xlog("L_NOTICE", "$ci|antiflood|authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
}
}
}
route[ANTIFLOOD_SUCCESSFUL_AUTH]
{
if($sel(cfg_get.kazoo.antiflood_failed_auth_use_port) == 1) {
sht_rm_name_re("antiflood=>$(Au{re.subst,/\\./\\\\./g})::$(si{re.subst,/\\./\\\\./g})::$sp::.*");
} else {
sht_rm_name_re("antiflood=>$(Au{re.subst,/\\./\\\\./g})::$(si{re.subst,/\\./\\\\./g})::.*");
}
}
route[ANTIFLOOD_RESET_AUTH]
{
$var(user) = $(kzE{kz.json,Username}) + "@" + $(kzE{kz.json,Realm});
sht_rm_name_re("antiflood=>$(var(user){re.subst,/\\./\\\\./g})::.*");
}
route[ANITFLOOD_FAILED_AUTH]
{
if (isflagset(FLAG_TRUSTED_SOURCE)) {
return;
}
$var(auth_key) = "";
if($sel(cfg_get.kazoo.antiflood_failed_auth_use_port) == 1) {
$var(auth_key) = $_s("$Au::$si::$sp");
} else {
$var(auth_key) = $_s("$Au::$si");
}
$var(count) = $shtinc(antiflood=>$var(auth_key)::count);
$sht(antiflood=>$var(auth_key)::last) = $Ts;
xlog("L_INFO", "$ci|antiflood|$var(count) errounous authorization response for $Au $si:$sp\n");
if ($var(count) >= ANTIFLOOD_FAILED_AUTH_DENSITY) {
$var(exp) = $Ts - ANTIFLOOD_FAILED_AUTH_WINDOW;
if($sht(antiflood=>$var(auth_key)::last) > $var(exp)) {
xlog("L_NOTICE", "$ci|end|request at authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
append_to_reply("Retry-After: 3600\r\n");
send_reply("403", "Forbidden");
exit;
}
}
}
event_route[htable:expired:antiflood]
{
xlog("L_NOTICE", "event|antiflood|antiflood expired record $shtrecord(key) => $shtrecord(value)\n");
}