1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-06 07:33:12 +02:00

Add set::anti-flood options lag-penalty and lag-penalty-sec.

This also allows known-users to execute slightly more commands per second.

For people who want their trusted users/bots to allow even more commands
per second (eg 20cmds/sec) we now have a nice FAQ item that uses this:
https://www.unrealircd.org/docs/FAQ#high-command-rate
This commit is contained in:
Bram Matthys
2021-06-23 16:19:45 +02:00
parent 28f98da5f8
commit e80c7b5b65
6 changed files with 79 additions and 1 deletions
+8
View File
@@ -33,6 +33,14 @@ Enhancements:
* New [security-group block](https://www.unrealircd.org/docs/Security-group_block)
item called *include-mask*. This can be used to put clients matching
a [mask](https://www.unrealircd.org/docs/Mask_item) into a security group.
* New option *lag-penalty* and *lag-penalty-bytes* in the
[set::anti-flood block](https://www.unrealircd.org/docs/Anti-flood_settings).
* *known-users* can now executes commands at a slightly faster rate than
*unknown-users*.
* It can further be used to allow really trusted users/bots to execute
commands at even higher rates, such as 20 commands per second,
without making them IRCOp. This explained in
[FAQ: How to allow users to send more commands per second](https://www.unrealircd.org/docs/FAQ#high-command-rate).
UnrealIRCd 5.2.0
-----------------
+2
View File
@@ -1225,6 +1225,7 @@ typedef enum FloodOption {
FLD_INVITE = 3, /**< invite-flood */
FLD_KNOCK = 4, /**< knock-flood */
FLD_CONVERSATIONS = 5, /**< max-concurrent-conversations */
FLD_LAG_PENALTY = 6, /**< lag-penalty / lag-penalty-bytes */
} FloodOption;
#define MAXFLOODOPTIONS 10
@@ -1268,6 +1269,7 @@ struct LocalClient {
int fd; /**< File descriptor, can be <0 if socket has been closed already. */
SSL *ssl; /**< OpenSSL/LibreSSL struct for SSL/TLS connection */
time_t since; /**< Time when user will next be allowed to send something (actually since<currenttime+10) */
int since_msec; /**< Used for calculating 'since' penalty (modulo) */
time_t firsttime; /**< Time user was created (connected on IRC) */
time_t lasttime; /**< Last time any message was received */
dbuf sendQ; /**< Outgoing send queue (data to be sent) */
+48
View File
@@ -1807,6 +1807,7 @@ void config_setdefaultsettings(Configuration *i)
config_parse_flood_generic("4:60", i, "known-users", FLD_INVITE); /* INVITE flood protection: max 4 per 60s */
config_parse_flood_generic("4:120", i, "known-users", FLD_KNOCK); /* KNOCK protection: max 4 per 120s */
config_parse_flood_generic("10:15", i, "known-users", FLD_CONVERSATIONS); /* 10 users, new user every 15s */
config_parse_flood_generic("180:750", i, "known-users", FLD_LAG_PENALTY); /* 180 bytes / 750 msec */
/* - unknown-users */
config_parse_flood_generic("2:60", i, "unknown-users", FLD_NICK); /* NICK flood protection: max 2 per 60s */
config_parse_flood_generic("2:90", i, "unknown-users", FLD_JOIN); /* JOIN flood protection: max 2 per 90s */
@@ -1814,6 +1815,7 @@ void config_setdefaultsettings(Configuration *i)
config_parse_flood_generic("2:60", i, "unknown-users", FLD_INVITE); /* INVITE flood protection: max 2 per 60s */
config_parse_flood_generic("2:120", i, "unknown-users", FLD_KNOCK); /* KNOCK protection: max 2 per 120s */
config_parse_flood_generic("4:15", i, "unknown-users", FLD_CONVERSATIONS); /* 4 users, new user every 15s */
config_parse_flood_generic("90:1000", i, "unknown-users", FLD_LAG_PENALTY); /* 90 bytes / 1000 msec */
/* SSL/TLS options */
i->tls_options = safe_alloc(sizeof(TLSOptions));
@@ -7681,6 +7683,8 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cep->ce_varname, "anti-flood")) {
for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
{
int lag_penalty = -1;
int lag_penalty_bytes = -1;
for (ceppp = cepp->ce_entries; ceppp; ceppp = ceppp->ce_next)
{
if (!strcmp(ceppp->ce_varname, "handshake-data-flood"))
@@ -7715,6 +7719,16 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
{
config_parse_flood_generic(ceppp->ce_vardata, &tempiConf, cepp->ce_varname, FLD_KNOCK);
}
else if (!strcmp(ceppp->ce_varname, "lag-penalty"))
{
lag_penalty = atoi(ceppp->ce_vardata);
}
else if (!strcmp(ceppp->ce_varname, "lag-penalty-bytes"))
{
lag_penalty_bytes = config_checkval(ceppp->ce_vardata, CFG_SIZE);
if (lag_penalty_bytes <= 0)
lag_penalty_bytes = INT_MAX;
}
else if (!strcmp(ceppp->ce_varname, "connect-flood"))
{
int cnt, period;
@@ -7752,6 +7766,13 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce)
}
}
}
if ((lag_penalty != -1) && (lag_penalty_bytes != -1))
{
/* We use a hack here to make it fit our storage format */
char buf[64];
snprintf(buf, sizeof(buf), "%d:%d", lag_penalty_bytes, lag_penalty);
config_parse_flood_generic(buf, &tempiConf, cepp->ce_varname, FLD_LAG_PENALTY);
}
}
}
else if (!strcmp(cep->ce_varname, "options")) {
@@ -8508,6 +8529,9 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
{
int has_lag_penalty = 0;
int has_lag_penalty_bytes = 0;
/* Test for old options: */
if (flood_option_is_old(cepp->ce_varname))
{
@@ -8721,6 +8745,24 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
errors++;
}
}
else if (!strcmp(ceppp->ce_varname, "lag-penalty"))
{
int v;
CheckNull(ceppp);
v = atoi(ceppp->ce_vardata);
has_lag_penalty = 1;
if ((v < 0) || (v > 10000))
{
config_error("%s:%i: set::anti-flood::%s::lag-penalty: value is in milliseconds and should be between 0 and 10000",
ceppp->ce_fileptr->cf_filename, ceppp->ce_varlinenum, cepp->ce_varname);
errors++;
}
}
else if (!strcmp(ceppp->ce_varname, "lag-penalty-bytes"))
{
has_lag_penalty_bytes = 1;
CheckNull(ceppp);
}
else if (!strcmp(ceppp->ce_varname, "connect-flood"))
{
int cnt, period;
@@ -8782,6 +8824,12 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce)
continue;
}
}
if (has_lag_penalty+has_lag_penalty_bytes == 1)
{
config_error("%s:%i: set::anti-flood::%s: if you use lag-penalty then you must also add an lag-penalty-bytes item (and vice-versa)",
cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname);
errors++;
}
}
/* Now the warnings: */
if (anti_flood_old == 1)
+8
View File
@@ -796,6 +796,14 @@ static void stats_set_anti_flood(Client *client, FloodSettings *f)
f->name, floodoption_names[i],
(int)f->limit[i], pretty_time_val(f->period[i]));
}
if (i == FLD_LAG_PENALTY)
{
sendtxtnumeric(client, "anti-flood::%s::lag-penalty: %d msec",
f->name, (int)f->period[i]);
sendtxtnumeric(client, "anti-flood::%s::lag-penalty-bytes: %d",
f->name,
f->limit[i] == INT_MAX ? 0 : (int)f->limit[i]);
}
else
{
sendtxtnumeric(client, "anti-flood::%s::%s: %d per %s",
+12 -1
View File
@@ -573,13 +573,24 @@ static void ban_handshake_data_flooder(Client *client)
*/
void parse_addlag(Client *client, int cmdbytes)
{
FloodSettings *settings = get_floodsettings_for_user(client, FLD_LAG_PENALTY);
if (!IsServer(client) && !IsNoFakeLag(client) &&
#ifdef FAKELAG_CONFIGURABLE
!(client->local->class && (client->local->class->options & CLASS_OPT_NOFAKELAG)) &&
#endif
!ValidatePermissionsForPath("immune:lag",client,NULL,NULL,NULL))
{
client->local->since += (1 + cmdbytes/90);
int lag_penalty = settings->period[FLD_LAG_PENALTY];
int lag_penalty_bytes = settings->limit[FLD_LAG_PENALTY];
client->local->since_msec += (1 + (cmdbytes/lag_penalty_bytes)) * lag_penalty;
/* This code takes into account not only the msecs we just calculated
* but also any leftover msec from previous lagging up.
*/
client->local->since += (client->local->since_msec / 1000);
client->local->since_msec = client->local->since_msec % 1000;
}
}
+1
View File
@@ -1086,5 +1086,6 @@ MODVAR char *floodoption_names[] = {
"invite-flood",
"knock-flood",
"max-concurrent-conversations",
"lag-penalty",
NULL
};