Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 7569:80359395b345
HTTP/2: traffic-based flood detection.
With this patch, all traffic over an HTTP/2 connection is counted in
the h2c->total_bytes field, and payload traffic is counted in
the h2c->payload_bytes field. As long as total traffic is many times
larger than payload traffic, we consider this to be a flood.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 18 Sep 2019 20:28:12 +0300 |
parents | 2e61e4b6bcd9 |
children | d6cf51af8a3d |
comparison
equal
deleted
inserted
replaced
7568:2e61e4b6bcd9 | 7569:80359395b345 |
---|---|
417 return; | 417 return; |
418 } | 418 } |
419 | 419 |
420 } while (p != end); | 420 } while (p != end); |
421 | 421 |
422 h2c->total_bytes += n; | |
423 | |
424 if (h2c->total_bytes / 8 > h2c->payload_bytes + 1048576) { | |
425 ngx_log_error(NGX_LOG_INFO, c->log, 0, "http2 flood detected"); | |
426 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); | |
427 return; | |
428 } | |
429 | |
422 } while (rev->ready); | 430 } while (rev->ready); |
423 | 431 |
424 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | 432 if (ngx_handle_read_event(rev, 0) != NGX_OK) { |
425 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR); | 433 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR); |
426 return; | 434 return; |
960 | 968 |
961 if (size >= h2c->state.length) { | 969 if (size >= h2c->state.length) { |
962 size = h2c->state.length; | 970 size = h2c->state.length; |
963 stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; | 971 stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; |
964 } | 972 } |
973 | |
974 h2c->payload_bytes += size; | |
965 | 975 |
966 if (r->request_body) { | 976 if (r->request_body) { |
967 rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); | 977 rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); |
968 | 978 |
969 if (rc != NGX_OK) { | 979 if (rc != NGX_OK) { |
2907 { | 2917 { |
2908 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, | 2918 ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, |
2909 "requested control frame is too large: %uz", length); | 2919 "requested control frame is too large: %uz", length); |
2910 return NULL; | 2920 return NULL; |
2911 } | 2921 } |
2922 #endif | |
2912 | 2923 |
2913 frame->length = length; | 2924 frame->length = length; |
2914 #endif | |
2915 | 2925 |
2916 buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type); | 2926 buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type); |
2917 | 2927 |
2918 *buf->last++ = flags; | 2928 *buf->last++ = flags; |
2919 | 2929 |
2935 return NGX_AGAIN; | 2945 return NGX_AGAIN; |
2936 } | 2946 } |
2937 | 2947 |
2938 frame->next = h2c->free_frames; | 2948 frame->next = h2c->free_frames; |
2939 h2c->free_frames = frame; | 2949 h2c->free_frames = frame; |
2950 | |
2951 h2c->total_bytes += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; | |
2940 | 2952 |
2941 return NGX_OK; | 2953 return NGX_OK; |
2942 } | 2954 } |
2943 | 2955 |
2944 | 2956 |
3721 | 3733 |
3722 | 3734 |
3723 static void | 3735 static void |
3724 ngx_http_v2_run_request(ngx_http_request_t *r) | 3736 ngx_http_v2_run_request(ngx_http_request_t *r) |
3725 { | 3737 { |
3726 ngx_connection_t *fc; | 3738 ngx_connection_t *fc; |
3739 ngx_http_v2_connection_t *h2c; | |
3727 | 3740 |
3728 fc = r->connection; | 3741 fc = r->connection; |
3729 | 3742 |
3730 if (ngx_http_v2_construct_request_line(r) != NGX_OK) { | 3743 if (ngx_http_v2_construct_request_line(r) != NGX_OK) { |
3731 goto failed; | 3744 goto failed; |
3752 } | 3765 } |
3753 | 3766 |
3754 if (r->headers_in.content_length_n == -1 && !r->stream->in_closed) { | 3767 if (r->headers_in.content_length_n == -1 && !r->stream->in_closed) { |
3755 r->headers_in.chunked = 1; | 3768 r->headers_in.chunked = 1; |
3756 } | 3769 } |
3770 | |
3771 h2c = r->stream->connection; | |
3772 | |
3773 h2c->payload_bytes += r->request_length; | |
3757 | 3774 |
3758 ngx_http_process_request(r); | 3775 ngx_http_process_request(r); |
3759 | 3776 |
3760 failed: | 3777 failed: |
3761 | 3778 |