summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Ermilov <ru@nginx.com>2018-11-06 16:29:35 +0300
committerRuslan Ermilov <ru@nginx.com>2018-11-06 16:29:35 +0300
commit65b2c00d624f17892c777f8fb5bb9c623cff5188 (patch)
treed8b30d2d51cd7d64ee6c9a374bce39f2112c2171
parent1d4c2fb6da12f3d103849cb9384687213f1656cf (diff)
downloadnginx-65b2c00d624f17892c777f8fb5bb9c623cff5188.tar.gz
HTTP/2: flood detection.
Fixed uncontrolled memory growth in case peer is flooding us with some frames (e.g., SETTINGS and PING) and doesn't read data. Fix is to limit the number of allocated control frames.
-rw-r--r--src/http/v2/ngx_http_v2.c12
-rw-r--r--src/http/v2/ngx_http_v2.h1
2 files changed, 12 insertions, 1 deletions
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index 77ebb8474..17d7cad04 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -664,6 +664,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
h2c->pool = NULL;
h2c->free_frames = NULL;
+ h2c->frames = 0;
h2c->free_fake_connections = NULL;
#if (NGX_HTTP_SSL)
@@ -2895,7 +2896,7 @@ ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length,
frame->blocked = 0;
- } else {
+ } else if (h2c->frames < 10000) {
pool = h2c->pool ? h2c->pool : h2c->connection->pool;
frame = ngx_pcalloc(pool, sizeof(ngx_http_v2_out_frame_t));
@@ -2919,6 +2920,15 @@ ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length,
frame->last = frame->first;
frame->handler = ngx_http_v2_frame_handler;
+
+ h2c->frames++;
+
+ } else {
+ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
+ "http2 flood detected");
+
+ h2c->connection->error = 1;
+ return NULL;
}
#if (NGX_DEBUG)
diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h
index ebd0e77c0..e8eaebb25 100644
--- a/src/http/v2/ngx_http_v2.h
+++ b/src/http/v2/ngx_http_v2.h
@@ -120,6 +120,7 @@ struct ngx_http_v2_connection_s {
ngx_http_connection_t *http_connection;
ngx_uint_t processing;
+ ngx_uint_t frames;
ngx_uint_t pushing;
ngx_uint_t concurrent_pushes;