Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_output.c @ 9190:3a67dd34b6cc
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.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 22 Nov 2023 14:52:21 +0400 |
parents | fcec773dd249 |
children | efcdaa66df2e |
comparison
equal
deleted
inserted
replaced
9189:fcec773dd249 | 9190:3a67dd34b6cc |
---|---|
1179 | 1179 |
1180 ngx_int_t | 1180 ngx_int_t |
1181 ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame, | 1181 ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame, |
1182 size_t min, ngx_quic_path_t *path) | 1182 size_t min, ngx_quic_path_t *path) |
1183 { | 1183 { |
1184 size_t min_payload, pad; | 1184 size_t max, max_payload, min_payload, pad; |
1185 ssize_t len, sent; | 1185 ssize_t len, sent; |
1186 ngx_str_t res; | 1186 ngx_str_t res; |
1187 ngx_quic_header_t pkt; | 1187 ngx_quic_header_t pkt; |
1188 ngx_quic_send_ctx_t *ctx; | 1188 ngx_quic_send_ctx_t *ctx; |
1189 ngx_quic_connection_t *qc; | 1189 ngx_quic_connection_t *qc; |
1192 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 1192 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
1193 | 1193 |
1194 qc = ngx_quic_get_connection(c); | 1194 qc = ngx_quic_get_connection(c); |
1195 ctx = ngx_quic_get_send_ctx(qc, frame->level); | 1195 ctx = ngx_quic_get_send_ctx(qc, frame->level); |
1196 | 1196 |
1197 max = ngx_quic_path_limit(c, path, path->mtu); | |
1198 | |
1199 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1200 "quic sendto %s packet max:%uz min:%uz", | |
1201 ngx_quic_level_name(ctx->level), max, min); | |
1202 | |
1197 ngx_quic_init_packet(c, ctx, &pkt, path); | 1203 ngx_quic_init_packet(c, ctx, &pkt, path); |
1198 | 1204 |
1199 min = ngx_quic_path_limit(c, path, min); | 1205 min_payload = ngx_quic_payload_size(&pkt, min); |
1200 | 1206 max_payload = ngx_quic_payload_size(&pkt, max); |
1201 min_payload = min ? ngx_quic_payload_size(&pkt, min) : 0; | 1207 |
1202 | 1208 /* RFC 9001, 5.4.2. Header Protection Sample */ |
1203 pad = 4 - pkt.num_len; | 1209 pad = 4 - pkt.num_len; |
1204 min_payload = ngx_max(min_payload, pad); | 1210 min_payload = ngx_max(min_payload, pad); |
1211 | |
1212 if (min_payload > max_payload) { | |
1213 return NGX_AGAIN; | |
1214 } | |
1205 | 1215 |
1206 #if (NGX_DEBUG) | 1216 #if (NGX_DEBUG) |
1207 frame->pnum = pkt.number; | 1217 frame->pnum = pkt.number; |
1208 #endif | 1218 #endif |
1209 | 1219 |
1210 ngx_quic_log_frame(c->log, frame, 1); | 1220 ngx_quic_log_frame(c->log, frame, 1); |
1211 | 1221 |
1212 len = ngx_quic_create_frame(NULL, frame); | 1222 len = ngx_quic_create_frame(NULL, frame); |
1213 if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) { | 1223 if ((size_t) len > max_payload) { |
1214 return NGX_ERROR; | 1224 return NGX_AGAIN; |
1215 } | 1225 } |
1216 | 1226 |
1217 len = ngx_quic_create_frame(src, frame); | 1227 len = ngx_quic_create_frame(src, frame); |
1218 if (len == -1) { | 1228 if (len == -1) { |
1219 return NGX_ERROR; | 1229 return NGX_ERROR; |
1256 if (!path->validated) { | 1266 if (!path->validated) { |
1257 max = path->received * 3; | 1267 max = path->received * 3; |
1258 max = (path->sent >= max) ? 0 : max - path->sent; | 1268 max = (path->sent >= max) ? 0 : max - path->sent; |
1259 | 1269 |
1260 if ((off_t) size > max) { | 1270 if ((off_t) size > max) { |
1261 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1262 "quic path limit %uz - %O", size, max); | |
1263 return max; | 1271 return max; |
1264 } | 1272 } |
1265 } | 1273 } |
1266 | 1274 |
1267 return size; | 1275 return size; |