Mercurial > hg > nginx
view src/event/quic/ngx_event_quic.h @ 8913:40445fc7c403 quic
QUIC: fixed migration during NAT rebinding.
The RFC 9000 allows a packet from known CID arrive from unknown path:
These requirements regarding connection ID reuse apply only to the
sending of packets, as unintentional changes in path without a change
in connection ID are possible. For example, after a period of
network inactivity, NAT rebinding might cause packets to be sent on a
new path when the client resumes sending.
Before the patch, such packets were rejected with an error in the
ngx_quic_check_migration() function. Removing the check makes the
separate function excessive - remaining checks are early migration
check and "disable_active_migration" check. The latter is a transport
parameter sent to client and it should not be used by server.
The server should send "disable_active_migration" "if the endpoint does
not support active connection migration" (18.2). The support status depends
on nginx configuration: to have migration working with multiple workers,
you need bpf helper, available on recent Linux systems. The patch does
not set "disable_active_migration" automatically and leaves it for the
administrator. By default, active migration is enabled.
RFC 900 says that it is ok to migrate if the peer violates
"disable_active_migration" flag requirements:
If the peer violates this requirement,
the endpoint MUST either drop the incoming packets on that path without
generating a Stateless Reset
OR
proceed with path validation and allow the peer to migrate. Generating a
Stateless Reset or closing the connection would allow third parties in the
network to cause connections to close by spoofing or otherwise manipulating
observed traffic.
So, nginx adheres to the second option and proceeds to path validation.
Note:
The ngtcp2 may be used for testing both active migration and NAT rebinding:
ngtcp2/client --change-local-addr=200ms --delay-stream=500ms <ip> <port> <url>
ngtcp2/client --change-local-addr=200ms --delay-stream=500ms --nat-rebinding \
<ip> <port> <url>
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Mon, 29 Nov 2021 11:51:14 +0300 |
parents | 41caf5410110 |
children | d6ef13c5fd8e |
line wrap: on
line source
/* * Copyright (C) Nginx, Inc. */ #ifndef _NGX_EVENT_QUIC_H_INCLUDED_ #define _NGX_EVENT_QUIC_H_INCLUDED_ #include <ngx_config.h> #include <ngx_core.h> #define NGX_QUIC_MAX_UDP_PAYLOAD_SIZE 65527 #define NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT 3 #define NGX_QUIC_DEFAULT_MAX_ACK_DELAY 25 #define NGX_QUIC_DEFAULT_HOST_KEY_LEN 32 #define NGX_QUIC_SR_KEY_LEN 32 #define NGX_QUIC_AV_KEY_LEN 32 #define NGX_QUIC_SR_TOKEN_LEN 16 #define NGX_QUIC_MIN_INITIAL_SIZE 1200 #define NGX_QUIC_STREAM_SERVER_INITIATED 0x01 #define NGX_QUIC_STREAM_UNIDIRECTIONAL 0x02 #define NGX_QUIC_STREAM_BUFSIZE 65536 typedef struct { /* configurable */ ngx_msec_t max_idle_timeout; ngx_msec_t max_ack_delay; size_t max_udp_payload_size; size_t initial_max_data; size_t initial_max_stream_data_bidi_local; size_t initial_max_stream_data_bidi_remote; size_t initial_max_stream_data_uni; ngx_uint_t initial_max_streams_bidi; ngx_uint_t initial_max_streams_uni; ngx_uint_t ack_delay_exponent; ngx_uint_t active_connection_id_limit; ngx_flag_t disable_active_migration; ngx_str_t original_dcid; ngx_str_t initial_scid; ngx_str_t retry_scid; u_char sr_token[NGX_QUIC_SR_TOKEN_LEN]; /* TODO */ void *preferred_address; } ngx_quic_tp_t; typedef struct { ngx_ssl_t *ssl; ngx_quic_tp_t tp; ngx_flag_t retry; ngx_flag_t gso_enabled; ngx_str_t host_key; ngx_int_t stream_close_code; ngx_int_t stream_reject_code_uni; ngx_int_t stream_reject_code_bidi; u_char av_token_key[NGX_QUIC_AV_KEY_LEN]; u_char sr_token_key[NGX_QUIC_SR_KEY_LEN]; } ngx_quic_conf_t; struct ngx_quic_stream_s { ngx_rbtree_node_t node; ngx_queue_t queue; ngx_connection_t *parent; ngx_connection_t *connection; uint64_t id; uint64_t acked; uint64_t send_max_data; uint64_t recv_max_data; uint64_t recv_offset; uint64_t recv_window; uint64_t recv_last; uint64_t final_size; ngx_chain_t *in; ngx_uint_t cancelable; /* unsigned cancelable:1; */ }; void ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf); ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi); void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, const char *reason); void ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_uint_t err, const char *reason); ngx_int_t ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err); ngx_int_t ngx_quic_shutdown_stream(ngx_connection_t *c, int how); uint32_t ngx_quic_version(ngx_connection_t *c); ngx_int_t ngx_quic_handle_read_event(ngx_event_t *rev, ngx_uint_t flags); ngx_int_t ngx_quic_handle_write_event(ngx_event_t *wev, size_t lowat); ngx_int_t ngx_quic_get_packet_dcid(ngx_log_t *log, u_char *data, size_t len, ngx_str_t *dcid); ngx_int_t ngx_quic_derive_key(ngx_log_t *log, const char *label, ngx_str_t *secret, ngx_str_t *salt, u_char *out, size_t len); #endif /* _NGX_EVENT_QUIC_H_INCLUDED_ */