Mercurial > hg > nginx
comparison src/http/v3/ngx_http_v3_request.c @ 8881:72b304f6207c quic
HTTP/3: traffic-based flood detection.
With this patch, all traffic over HTTP/3 bidi and uni streams is counted in
the h3c->total_bytes field, and payload traffic is counted in the
h3c->payload_bytes field. As long as total traffic is many times larger than
payload traffic, we consider this to be a flood.
Request header traffic is counted as if all fields are literal. Response
header traffic is counted as is.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 07 Oct 2021 13:22:42 +0300 |
parents | a09bcc304eef |
children | 925572184d4a |
comparison
equal
deleted
inserted
replaced
8880:a09bcc304eef | 8881:72b304f6207c |
---|---|
216 ssize_t n; | 216 ssize_t n; |
217 ngx_buf_t *b; | 217 ngx_buf_t *b; |
218 ngx_int_t rc; | 218 ngx_int_t rc; |
219 ngx_connection_t *c; | 219 ngx_connection_t *c; |
220 ngx_http_request_t *r; | 220 ngx_http_request_t *r; |
221 ngx_http_v3_session_t *h3c; | |
221 ngx_http_core_srv_conf_t *cscf; | 222 ngx_http_core_srv_conf_t *cscf; |
222 ngx_http_v3_parse_headers_t *st; | 223 ngx_http_v3_parse_headers_t *st; |
223 | 224 |
224 c = rev->data; | 225 c = rev->data; |
225 r = c->data; | 226 r = c->data; |
230 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | 231 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); |
231 c->timedout = 1; | 232 c->timedout = 1; |
232 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); | 233 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); |
233 return; | 234 return; |
234 } | 235 } |
236 | |
237 h3c = ngx_http_v3_get_session(c); | |
235 | 238 |
236 st = &r->v3_parse->headers; | 239 st = &r->v3_parse->headers; |
237 | 240 |
238 b = r->header_in; | 241 b = r->header_in; |
239 | 242 |
296 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 299 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
297 break; | 300 break; |
298 } | 301 } |
299 | 302 |
300 r->request_length += b->pos - p; | 303 r->request_length += b->pos - p; |
304 h3c->total_bytes += b->pos - p; | |
305 | |
306 if (ngx_http_v3_check_flood(c) != NGX_OK) { | |
307 ngx_http_close_request(r, NGX_HTTP_CLOSE); | |
308 break; | |
309 } | |
301 | 310 |
302 if (rc == NGX_BUSY) { | 311 if (rc == NGX_BUSY) { |
303 if (rev->error) { | 312 if (rev->error) { |
304 ngx_http_close_request(r, NGX_HTTP_CLOSE); | 313 ngx_http_close_request(r, NGX_HTTP_CLOSE); |
305 break; | 314 break; |
315 if (rc == NGX_AGAIN) { | 324 if (rc == NGX_AGAIN) { |
316 continue; | 325 continue; |
317 } | 326 } |
318 | 327 |
319 /* rc == NGX_OK || rc == NGX_DONE */ | 328 /* rc == NGX_OK || rc == NGX_DONE */ |
329 | |
330 h3c->payload_bytes += ngx_http_v3_encode_field_l(NULL, | |
331 &st->field_rep.field.name, | |
332 &st->field_rep.field.value); | |
320 | 333 |
321 if (ngx_http_v3_process_header(r, &st->field_rep.field.name, | 334 if (ngx_http_v3_process_header(r, &st->field_rep.field.name, |
322 &st->field_rep.field.value) | 335 &st->field_rep.field.value) |
323 != NGX_OK) | 336 != NGX_OK) |
324 { | 337 { |
1078 u_char *p; | 1091 u_char *p; |
1079 ngx_int_t rc; | 1092 ngx_int_t rc; |
1080 ngx_buf_t *b; | 1093 ngx_buf_t *b; |
1081 ngx_uint_t last; | 1094 ngx_uint_t last; |
1082 ngx_chain_t *cl, *out, *tl, **ll; | 1095 ngx_chain_t *cl, *out, *tl, **ll; |
1096 ngx_http_v3_session_t *h3c; | |
1083 ngx_http_request_body_t *rb; | 1097 ngx_http_request_body_t *rb; |
1084 ngx_http_core_loc_conf_t *clcf; | 1098 ngx_http_core_loc_conf_t *clcf; |
1085 ngx_http_core_srv_conf_t *cscf; | 1099 ngx_http_core_srv_conf_t *cscf; |
1086 ngx_http_v3_parse_data_t *st; | 1100 ngx_http_v3_parse_data_t *st; |
1087 | 1101 |
1088 rb = r->request_body; | 1102 rb = r->request_body; |
1089 st = &r->v3_parse->body; | 1103 st = &r->v3_parse->body; |
1104 | |
1105 h3c = ngx_http_v3_get_session(r->connection); | |
1090 | 1106 |
1091 if (rb->rest == -1) { | 1107 if (rb->rest == -1) { |
1092 | 1108 |
1093 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1109 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1094 "http3 request body filter"); | 1110 "http3 request body filter"); |
1133 p = cl->buf->pos; | 1149 p = cl->buf->pos; |
1134 | 1150 |
1135 rc = ngx_http_v3_parse_data(r->connection, st, cl->buf); | 1151 rc = ngx_http_v3_parse_data(r->connection, st, cl->buf); |
1136 | 1152 |
1137 r->request_length += cl->buf->pos - p; | 1153 r->request_length += cl->buf->pos - p; |
1154 h3c->total_bytes += cl->buf->pos - p; | |
1155 | |
1156 if (ngx_http_v3_check_flood(r->connection) != NGX_OK) { | |
1157 return NGX_HTTP_CLOSE; | |
1158 } | |
1138 | 1159 |
1139 if (rc == NGX_AGAIN) { | 1160 if (rc == NGX_AGAIN) { |
1140 continue; | 1161 continue; |
1141 } | 1162 } |
1142 | 1163 |
1176 && st->length <= 128 | 1197 && st->length <= 128 |
1177 && (uint64_t) (cl->buf->last - cl->buf->pos) >= st->length) | 1198 && (uint64_t) (cl->buf->last - cl->buf->pos) >= st->length) |
1178 { | 1199 { |
1179 rb->received += st->length; | 1200 rb->received += st->length; |
1180 r->request_length += st->length; | 1201 r->request_length += st->length; |
1202 h3c->total_bytes += st->length; | |
1203 h3c->payload_bytes += st->length; | |
1181 | 1204 |
1182 if (st->length < 8) { | 1205 if (st->length < 8) { |
1183 | 1206 |
1184 while (st->length) { | 1207 while (st->length) { |
1185 *b->last++ = *cl->buf->pos++; | 1208 *b->last++ = *cl->buf->pos++; |
1220 | 1243 |
1221 if (size > st->length) { | 1244 if (size > st->length) { |
1222 cl->buf->pos += (size_t) st->length; | 1245 cl->buf->pos += (size_t) st->length; |
1223 rb->received += st->length; | 1246 rb->received += st->length; |
1224 r->request_length += st->length; | 1247 r->request_length += st->length; |
1248 h3c->total_bytes += st->length; | |
1249 h3c->payload_bytes += st->length; | |
1225 st->length = 0; | 1250 st->length = 0; |
1226 | 1251 |
1227 } else { | 1252 } else { |
1228 st->length -= size; | 1253 st->length -= size; |
1229 rb->received += size; | 1254 rb->received += size; |
1230 r->request_length += size; | 1255 r->request_length += size; |
1256 h3c->total_bytes += size; | |
1257 h3c->payload_bytes += size; | |
1231 cl->buf->pos = cl->buf->last; | 1258 cl->buf->pos = cl->buf->last; |
1232 } | 1259 } |
1233 | 1260 |
1234 b->last = cl->buf->pos; | 1261 b->last = cl->buf->pos; |
1235 } | 1262 } |