aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2023-11-22 14:52:21 +0400
committerRoman Arutyunyan <arut@nginx.com>2023-11-22 14:52:21 +0400
commit6c78bb9bb1ccbf91f5f059c13a82badea529012a (patch)
treed71cac4f8adb32c40ee21d46efa94e13e9c45527 /src
parent0efe8db1d0c331bad799dcaa0b2a24e739f26c98 (diff)
downloadnginx-6c78bb9bb1ccbf91f5f059c13a82badea529012a.tar.gz
nginx-6c78bb9bb1ccbf91f5f059c13a82badea529012a.zip
QUIC: fixed anti-amplification with explicit send.
Previously, when using ngx_quic_frame_sendto() to explicitly send a packet with a single frame, anti-amplification limit was not properly enforced. Even when there was no quota left for the packet, it was sent anyway, but with no padding. Now the packet is not sent at all. This function is called to send PATH_CHALLENGE/PATH_RESPONSE, PMTUD and probe packets. For all these cases packet send is retried later in case the send was not successful.
Diffstat (limited to 'src')
-rw-r--r--src/event/quic/ngx_event_quic_migration.c6
-rw-r--r--src/event/quic/ngx_event_quic_output.c24
2 files changed, 22 insertions, 8 deletions
diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c
index 2fccafa41..efb167b0a 100644
--- a/src/event/quic/ngx_event_quic_migration.c
+++ b/src/event/quic/ngx_event_quic_migration.c
@@ -872,6 +872,7 @@ ngx_quic_expire_path_mtu_discovery(ngx_connection_t *c, ngx_quic_path_t *path)
static ngx_int_t
ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
{
+ size_t mtu;
ngx_int_t rc;
ngx_uint_t log_error;
ngx_quic_frame_t frame;
@@ -895,7 +896,12 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
log_error = c->log_error;
c->log_error = NGX_ERROR_IGNORE_EMSGSIZE;
+ mtu = path->mtu;
+ path->mtu = path->mtud;
+
rc = ngx_quic_frame_sendto(c, &frame, path->mtud, path);
+
+ path->mtu = mtu;
c->log_error = log_error;
if (rc == NGX_ERROR) {
diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c
index a0acdb700..338451e8b 100644
--- a/src/event/quic/ngx_event_quic_output.c
+++ b/src/event/quic/ngx_event_quic_output.c
@@ -1181,7 +1181,7 @@ ngx_int_t
ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
size_t min, ngx_quic_path_t *path)
{
- size_t min_payload, pad;
+ size_t max, max_payload, min_payload, pad;
ssize_t len, sent;
ngx_str_t res;
ngx_quic_header_t pkt;
@@ -1194,15 +1194,25 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, frame->level);
- ngx_quic_init_packet(c, ctx, &pkt, path);
+ max = ngx_quic_path_limit(c, path, path->mtu);
- min = ngx_quic_path_limit(c, path, min);
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "quic sendto %s packet max:%uz min:%uz",
+ ngx_quic_level_name(ctx->level), max, min);
- min_payload = min ? ngx_quic_payload_size(&pkt, min) : 0;
+ ngx_quic_init_packet(c, ctx, &pkt, path);
+
+ min_payload = ngx_quic_payload_size(&pkt, min);
+ max_payload = ngx_quic_payload_size(&pkt, max);
+ /* RFC 9001, 5.4.2. Header Protection Sample */
pad = 4 - pkt.num_len;
min_payload = ngx_max(min_payload, pad);
+ if (min_payload > max_payload) {
+ return NGX_AGAIN;
+ }
+
#if (NGX_DEBUG)
frame->pnum = pkt.number;
#endif
@@ -1210,8 +1220,8 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
ngx_quic_log_frame(c->log, frame, 1);
len = ngx_quic_create_frame(NULL, frame);
- if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) {
- return NGX_ERROR;
+ if ((size_t) len > max_payload) {
+ return NGX_AGAIN;
}
len = ngx_quic_create_frame(src, frame);
@@ -1258,8 +1268,6 @@ ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path, size_t size)
max = (path->sent >= max) ? 0 : max - path->sent;
if ((off_t) size > max) {
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic path limit %uz - %O", size, max);
return max;
}
}