]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/worker: robustness against the slow-lorris attack
authorGrigorii Demidov <grigorii.demidov@nic.cz>
Fri, 13 Apr 2018 08:19:14 +0000 (10:19 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Mon, 23 Apr 2018 07:48:45 +0000 (09:48 +0200)
daemon/worker.c

index 6edd39baf95757f882024a9d39849df463374c8b..2469d4ed49b1c01d5bbb2d941d12d8bbf16ad446 100644 (file)
@@ -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 */