[PATCH 4 of 5] QUIC: traffic-based flood detection

Roman Arutyunyan arut at nginx.com
Thu Oct 7 11:36:17 UTC 2021


# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1633602816 -10800
#      Thu Oct 07 13:33:36 2021 +0300
# Branch quic
# Node ID e20f00b8ac9005621993ea19375b1646c9182e7b
# Parent  31561ac584b74d29af9a442afca47821a98217b2
QUIC: traffic-based flood detection.

With this patch, all traffic over a QUIC connection is compared to traffic
over QUIC streams.  As long as total traffic is many times larger than stream
traffic, we consider this to be a flood.

diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c
--- a/src/event/quic/ngx_event_quic.c
+++ b/src/event/quic/ngx_event_quic.c
@@ -662,13 +662,17 @@ ngx_quic_close_timer_handler(ngx_event_t
 static ngx_int_t
 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf)
 {
-    u_char             *p;
-    ngx_int_t           rc;
-    ngx_uint_t          good;
-    ngx_quic_header_t   pkt;
+    size_t                  size;
+    u_char                 *p;
+    ngx_int_t               rc;
+    ngx_uint_t              good;
+    ngx_quic_header_t       pkt;
+    ngx_quic_connection_t  *qc;
 
     good = 0;
 
+    size = b->last - b->pos;
+
     p = b->pos;
 
     while (p < b->last) {
@@ -701,7 +705,8 @@ ngx_quic_input(ngx_connection_t *c, ngx_
 
         if (rc == NGX_DONE) {
             /* stop further processing */
-            return NGX_DECLINED;
+            good = 0;
+            break;
         }
 
         if (rc == NGX_OK) {
@@ -733,7 +738,27 @@ ngx_quic_input(ngx_connection_t *c, ngx_
         p = b->pos;
     }
 
-    return good ? NGX_OK : NGX_DECLINED;
+    if (!good) {
+        return NGX_DECLINED;
+    }
+
+    qc = ngx_quic_get_connection(c);
+
+    if (qc) {
+        qc->received += size;
+
+        if ((uint64_t) (c->sent + qc->received) / 8 >
+            (qc->streams.sent + qc->streams.recv_last) + 1048576)
+        {
+            ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic flood detected");
+
+            qc->error = NGX_QUIC_ERR_NO_ERROR;
+            qc->error_reason = "QUIC flood detected";
+            return NGX_ERROR;
+        }
+    }
+
+    return NGX_OK;
 }
 
 
diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h
--- a/src/event/quic/ngx_event_quic_connection.h
+++ b/src/event/quic/ngx_event_quic_connection.h
@@ -236,6 +236,8 @@ struct ngx_quic_connection_s {
     ngx_quic_streams_t                streams;
     ngx_quic_congestion_t             congestion;
 
+    off_t                             received;
+
     ngx_uint_t                        error;
     enum ssl_encryption_level_t       error_level;
     ngx_uint_t                        error_ftype;


More information about the nginx-devel mailing list