From 8ea37cc36d4f060af815c29de07b8411b8c3a98f Mon Sep 17 00:00:00 2001 From: Grigorii Demidov Date: Fri, 13 Apr 2018 10:19:14 +0200 Subject: [PATCH] daemon/worker: robustness against the slow-lorris attack --- daemon/worker.c | 57 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 6edd39baf..2469d4ed4 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -826,14 +826,12 @@ static int qr_task_on_send(struct qr_task *task, uv_handle_t *handle, int status if (session->waiting.len > 0) { struct qr_task *t = session->waiting.at[0]; int ret = qr_task_send(t, handle, &session->peer.ip, t->pktbuf); + uv_timer_t *timer = &session->timeout; + uv_timer_stop(timer); if (ret == kr_ok()) { - uv_timer_t *timer = &session->timeout; - uv_timer_stop(timer); session->timeout.data = session; timer_start(session, on_tcp_watchdog_timeout, MAX_TCP_INACTIVITY, 0); } else { - uv_timer_t *timer = &session->timeout; - uv_timer_stop(timer); while (session->waiting.len > 0) { struct qr_task *t = session->waiting.at[0]; if (session->outgoing) { @@ -1081,6 +1079,7 @@ static int session_next_waiting_send(struct session *session) struct qr_task *task = session->waiting.at[0]; ret = qr_task_send(task, session->handle, &peer->ip, task->pktbuf); } + uv_timer_stop(&session->timeout); session->timeout.data = session; timer_start(session, on_tcp_watchdog_timeout, MAX_TCP_INACTIVITY, 0); return ret; @@ -1693,8 +1692,9 @@ static int qr_task_step(struct qr_task *task, session_close(session); return qr_task_finalize(task, KR_STATE_FAIL); } + uv_timer_stop(&session->timeout); ret = timer_start(session, on_tcp_watchdog_timeout, - KR_CONN_RTT_MAX, 0); + MAX_TCP_INACTIVITY, 0); if (ret < 0) { session_del_waiting(session, task); session_del_tasks(session, task); @@ -2097,11 +2097,6 @@ int worker_process_tcp(struct worker_ctx *worker, uv_stream_t *handle, return kr_ok(); } - if (session->outgoing) { - uv_timer_stop(&session->timeout); - timer_start(session, on_tcp_watchdog_timeout, MAX_TCP_INACTIVITY, 0); - } - if (session->bytes_to_skip) { assert(session->buffering == NULL); ssize_t min_len = MIN(session->bytes_to_skip, len); @@ -2285,27 +2280,33 @@ int worker_process_tcp(struct worker_ctx *worker, uv_stream_t *handle, /* Message was assembled, clear temporary. */ session->buffering = NULL; session->msg_hdr_idx = 0; - if (session->outgoing) { - session_del_tasks(session, task); - } /* Parse the packet and start resolving complete query */ int ret = parse_packet(pkt_buf); - if (ret == 0 && !session->outgoing) { - /* Start only new queries, - * not subrequests that are already pending */ - ret = request_start(task->ctx, pkt_buf); - assert(ret == 0); - if (ret == 0) { - ret = qr_task_register(task, session); - } - if (ret == 0) { - submitted += 1; - } - if (task->leading) { - assert(false); - } - } if (ret == 0) { + if (session->outgoing) { + session_del_tasks(session, task); + /* To prevent slow lorris attack restart watchdog only after + * the whole message was successfully assembled and parsed */ + uv_timer_stop(&session->timeout); + if (session->tasks.len > 0) { + timer_start(session, on_tcp_watchdog_timeout, + MAX_TCP_INACTIVITY, 0); + } + } else { + /* Start only new queries, + * not subrequests that are already pending */ + ret = request_start(task->ctx, pkt_buf); + assert(ret == 0); + if (ret == 0) { + ret = qr_task_register(task, session); + } + if (ret == 0) { + submitted += 1; + } + if (task->leading) { + assert(false); + } + } const struct sockaddr *addr = session->outgoing ? &session->peer.ip : NULL; /* since there can be next dns message, we must to proceed * even if qr_task_step() returns error */ -- 2.47.2