[MEDIUM] add support for global.maxconnrate to limit the per-process conn rate.
This one enforces a per-process connection rate limit, regardless of what
may be set per frontend. It can be a way to limit the CPU usage of a process
being severely attacked.
The side effect is that the global process connection rate is now measured
for each incoming connection, so it will be possible to report it.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 5b942e2..1889654 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -682,6 +682,19 @@
}
#endif /* SYSTEM_MAXCONN */
}
+ else if (!strcmp(args[0], "maxconnrate")) {
+ if (global.cps_lim != 0) {
+ Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.cps_lim = atol(args[1]);
+ }
else if (!strcmp(args[0], "maxpipes")) {
if (global.maxpipes != 0) {
Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index c9c4055..4fde291 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -808,6 +808,7 @@
}
}
+ global.cps_max = 0;
return 1;
}
else if (strcmp(args[1], "table") == 0) {
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 11e74fd..365f52b 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -1156,6 +1156,20 @@
return 0;
}
+ if (global.cps_lim) {
+ int max = freq_ctr_remain(&global.conn_per_sec, global.cps_lim, 0);
+
+ if (unlikely(!max)) {
+ /* frontend accept rate limit was reached */
+ limit_listener(l, &global_listener_queue);
+ task_schedule(global_listener_queue_task, tick_add(now_ms, next_event_delay(&global.conn_per_sec, global.cps_lim, 0)));
+ return 0;
+ }
+
+ if (max_accept > max)
+ max_accept = max;
+ }
+
if (p && p->fe_sps_lim) {
int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
@@ -1237,6 +1251,11 @@
return 0;
}
+ /* increase the per-process number of cumulated connections */
+ update_freq_ctr(&global.conn_per_sec, 1);
+ if (global.conn_per_sec.curr_ctr > global.cps_max)
+ global.cps_max = global.conn_per_sec.curr_ctr;
+
jobs++;
actconn++;
totalconn++;