aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/redirector.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/redirector.c b/src/redirector.c
index be3802f..b4d7a78 100644
--- a/src/redirector.c
+++ b/src/redirector.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <signal.h>
#include <pthread.h>
+#include <time.h>
#include <assert.h>
#include "redirector.h"
@@ -21,6 +22,8 @@ typedef struct client_thread {
typedef struct server_event {
redirector_ctx **rdr_ctx;
const size_t siz;
+ size_t last_accept_count;
+ time_t last_accept_stamp;
} server_event;
typedef struct client_event {
@@ -222,11 +225,12 @@ fwd_state_string(const forward_state c_state, const client_thread *args,
static int redirector_mainloop(event_ctx **ev_ctx, redirector_ctx *rdr_ctx[], size_t siz)
{
int rc;
- server_event ev_srv = { rdr_ctx, siz };
+ server_event ev_srv = { rdr_ctx, siz, 0, 0 };
set_procname("[potd] redirector");
assert( set_child_sighandler() == 0 );
+ ev_srv.last_accept_stamp = time(NULL);
rc = event_loop(*ev_ctx, redirector_accept_client, &ev_srv);
event_free(ev_ctx);
@@ -236,7 +240,9 @@ static int redirector_mainloop(event_ctx **ev_ctx, redirector_ctx *rdr_ctx[], si
static int redirector_accept_client(event_ctx *ev_ctx, int fd, void *user_data)
{
size_t i;
+ double d;
int s;
+ time_t t;
server_event *ev_srv = (server_event *) user_data;
client_thread *args;
redirector_ctx *rdr_ctx;
@@ -258,6 +264,21 @@ static int redirector_accept_client(event_ctx *ev_ctx, int fd, void *user_data)
goto error;
}
+ ev_srv->last_accept_count++;
+ t = time(NULL);
+ d = difftime(t, ev_srv->last_accept_stamp);
+ if (d == 0.0f)
+ d = 1.0f;
+ if (d > 5.0f) {
+ ev_srv->last_accept_stamp = t;
+ ev_srv->last_accept_count = 0;
+ }
+ if (ev_srv->last_accept_count / (size_t)d > 3) {
+ W2("DoS protection: Got %zu accepts/s",
+ ev_srv->last_accept_count / (size_t)d);
+ goto error;
+ }
+
args->rdr_ctx = rdr_ctx;
s = socket_addrtostr_in(&args->client_sock,
args->host_buf, args->service_buf);