Commit graph

7766 commits

Author SHA1 Message Date
Vladimir Homutov
09e77a9751 QUIC: added missing check for backup path existence. 2021-12-16 11:42:28 +03:00
Ruslan Ermilov
da7d48ca9f Merged with the default branch. 2021-12-24 15:53:59 +03:00
Ruslan Ermilov
9cfe1fb704 Moved Huffman coding out of HTTP/2.
ngx_http_v2_huff_decode.c and ngx_http_v2_huff_encode.c are renamed
to ngx_http_huff_decode.c and ngx_http_huff_encode.c.
2021-12-21 07:54:16 +03:00
Gena Makhomed
281431875f Contrib: vim syntax, update core and 3rd party module directives. 2021-12-20 20:02:48 +02:00
Roman Arutyunyan
e6b7f80fb5 QUIC: added path limiting function ngx_quic_path_limit(). 2021-12-14 16:24:20 +03:00
Vladimir Homutov
6f57aada90 QUIC: decoupled path state and limitation status.
The path validation status and anti-amplification limit status is actually
two different variables.  It is possible that validating path should not
be limited (for example, when re-validating former path).
2021-12-13 09:48:33 +03:00
Vladimir Homutov
36f796fd76 QUIC: improved path validation.
Previously, path was considered valid during arbitrary selected 10m timeout
since validation.  This is quite not what RFC 9000 says; the relevant
part is:

    An endpoint MAY skip validation of a peer address if that
    address has been seen recently.

The patch considers a path to be 'recently seen' if packets were received
during idle timeout.  If a packet is received from the path that was seen
not so recently, such path is considered new, and anti-amplification
restrictions apply.
2021-12-13 17:27:29 +03:00
Roman Arutyunyan
fb6c936dad QUIC: write and full stream shutdown support.
Full stream shutdown is now called from stream cleanup handler instead of
explicitly sending frames.
2021-12-13 14:49:42 +03:00
Roman Arutyunyan
dca7a44179 QUIC: simplified stream initialization.
After creation, a client stream is added to qc->streams.uninitialized queue.
After initialization it's removed from the queue.  If a stream is never
initialized, it is freed in ngx_quic_close_streams().  Stream initializer
is now set as read event handler in stream connection.

Previously qc->streams.uninitialized was used only for delayed stream
initialization.

The change makes it possible not to handle separately the case of a new stream
in stream-related frame handlers.  It makes these handlers simpler since new
streams and existing streams are now handled by the same code.
2021-12-10 19:43:50 +03:00
Maxim Dounin
c7aee5eac3 HTTP/2: fixed sendfile() aio handling.
With sendfile() in threads ("aio threads; sendfile on;"), client connection
can block on writing, waiting for sendfile() to complete.  In HTTP/2 this
might result in the request hang, since an attempt to continue processing
in thread event handler will call request's write event handler, which
is usually stopped by ngx_http_v2_send_chain(): it does nothing if there
are no additional data and stream->queued is set.  Further, HTTP/2 resets
stream's c->write->ready to 0 if writing blocks, so just fixing
ngx_http_v2_send_chain() is not enough.

Can be reproduced with test suite on Linux with:

TEST_NGINX_GLOBALS_HTTP="aio threads; sendfile on;" prove h2*.t

The following tests currently fail: h2_keepalive.t, h2_priority.t,
h2_proxy_max_temp_file_size.t, h2.t, h2_trailers.t.

Similarly, sendfile() with AIO preloading on FreeBSD can block as well,
with similar results.  This is, however, harder to reproduce, especially
on modern FreeBSD systems, since sendfile() usually does not return EBUSY.

Fix is to modify ngx_http_v2_send_chain() so it actually tries to send
data to the main connection when called, and to make sure that
c->write->ready is set by the relevant event handlers.
2021-11-25 22:02:10 +03:00
Maxim Dounin
cb3ca0ba5d HTTP/2: fixed "task already active" with sendfile in threads.
With sendfile in threads, "task already active" alerts might appear in logs
if a write event happens on the main HTTP/2 connection, triggering a sendfile
in threads while another thread operation is already running.  Observed
with "aio threads; aio_write on; sendfile on;" and with thread event handlers
modified to post a write event to the main HTTP/2 connection (though can
happen without any modifications).

Similarly, sendfile() with AIO preloading on FreeBSD can trigger duplicate
aio operation, resulting in "second aio post" alerts.  This is, however,
harder to reproduce, especially on modern FreeBSD systems, since sendfile()
usually does not return EBUSY.

Fix is to avoid starting a sendfile operation if other thread operation
is active by checking r->aio in the thread handler (and, similarly, in
aio preload handler).  The added check also makes duplicate calls protection
redundant, so it is removed.
2021-11-25 22:02:05 +03:00
Roman Arutyunyan
2e04ad69ca QUIC: post stream events instead of calling their handlers.
This potentially reduces the number of handler calls.
2021-11-23 21:39:51 +03:00
Ruslan Ermilov
926e3d1fa2 QUIC: removed configure time test for BPF sockhash.
The test verifies kernel version on a build machine,
but actually used kernel may be different.
2021-12-09 15:30:50 +03:00
Ruslan Ermilov
8802f709d7 QUIC: configure cleanup.
Renamed and removed some macros.
2021-12-09 15:30:01 +03:00
Vladimir Homutov
6c742f75bc QUIC: added missing frame initialization.
Currently, all used fields are initialized, but usage may change in future.
2021-12-06 11:04:55 +03:00
Vladimir Homutov
5d7fa710ca QUIC: refactored ngx_quic_frame_sendto() function.
The function now takes path as an argument to deal with associated
restrictions and update sent counter.
2021-12-09 12:40:14 +03:00
Sergey Kandaurov
5917a86f5b QUIC: fixed e06283038ec8 mis-merge.
The NGX_HTTP_QUIC macro was removed in 33226ac61076.
2021-12-09 11:15:25 +03:00
Sergey Kandaurov
83a7622d32 HTTP/3: cleanup after "listen .. quic" removal in be08b858086a. 2021-12-08 17:04:56 +03:00
Vladimir Homutov
7519cf88b7 QUIC: updated README.
The ngx_http_quic_module is merged to ngx_http_v3_module.
The $quic variable no longer exists, it is replaced with $http3 variable.
2021-12-07 16:07:47 +03:00
Sergey Kandaurov
d0b788c0bd QUIC: clear SSL_OP_ENABLE_MIDDLEBOX_COMPAT on SSL context switch.
The SSL_OP_ENABLE_MIDDLEBOX_COMPAT option is provided by QuicTLS and enabled
by default in the newly created SSL contexts.  SSL_set_quic_method() is used
to clear it, which is required for SSL handshake to work on QUIC connections.
Switching context in the ngx_http_ssl_servername() SNI callback overrides SSL
options from the new SSL context.  This results in the option set again.
Fix is to explicitly clear it when switching to another SSL context.

Initially reported here (in Russian):
http://mailman.nginx.org/pipermail/nginx-ru/2021-November/063989.html
2021-12-07 15:49:51 +03:00
Sergey Kandaurov
41b87485eb HTTP/3: avoid sending stream cancellation for pushed streams. 2021-12-07 15:49:30 +03:00
Sergey Kandaurov
8a0a6a85f4 QUIC: converted ngx_quic_keys_set_encryption_secret() to NGX codes.
While here, removed check for encryption level zero, redundant by its nature.
2021-12-07 15:42:10 +03:00
Roman Arutyunyan
bd8e49cbc6 HTTP/3: renamed files.
ngx_http_v3_tables.h and ngx_http_v3_tables.c are renamed to
ngx_http_v3_table.h and ngx_http_v3_table.c to better match HTTP/2 code.

ngx_http_v3_streams.h and ngx_http_v3_streams.c are renamed to
ngx_http_v3_uni.h and ngx_http_v3_uni.c to better match their content.
2021-12-07 13:01:28 +03:00
Vladimir Homutov
c1d88961cb QUIC: simplified configuration.
Directives that set transport parameters are removed from the configuration.
Corresponding values are derived from the quic configuration or initialized
to default.  Whenever possible, quic configuration parameters are taken from
higher-level protocol settings, i.e. HTTP/3.
2021-12-06 15:19:54 +03:00
Roman Arutyunyan
52b891d39c HTTP/3: $http3 variable.
A new variable $http3 is added.  The variable equals to "h3" for HTTP/3
connections, "hq" for hq connections and is an empty string otherwise.

The variable $quic is eliminated.

The new variable is similar to $http2 variable.
2021-12-01 11:02:17 +03:00
Roman Arutyunyan
88d2f21fc9 HTTP/3: http3_hq directive and NGX_HTTP_V3_HQ macro.
Listen quic parameter is no longer supported.
2021-12-04 10:52:55 +03:00
Roman Arutyunyan
6dc747f5ff HTTP/3: merged ngx_http_quic_module into ngx_http_v3_module. 2021-12-06 13:02:36 +03:00
Vladimir Homutov
56feb8f3ca QUIC: fixed using of retired connection id (ticket #2289).
RFC 9000 19.16
 The sequence number specified in a RETIRE_CONNECTION_ID frame MUST NOT
 refer to the Destination Connection ID field of the packet in which the
 frame is contained.

Before the patch, the RETIRE_CONNECTION_ID frame was sent before switching
to the new client id.  If retired client id was currently in use, this lead
to violation of the spec.
2021-12-02 14:09:52 +03:00
Sergey Kandaurov
bde585656a QUIC: logging of CRYPTO frame payload under NGX_QUIC_DEBUG_FRAMES. 2021-12-02 13:59:56 +03:00
Sergey Kandaurov
1cf5df0781 HTTP/3: adjusted ALPN macro names to align with 61abb35bb8cf. 2021-12-02 13:59:09 +03:00
Vladimir Homutov
9b92d9600f QUIC: removed excessive check.
The c->udp->dgram may be NULL only if the quic connection was just
created: the ngx_event_udp_recvmsg() passes information about datagrams
to existing connections by providing information in c->udp.

If case of a new connection, c->udp is allocated by the QUIC code during
creation of quic connection (it uses c->sockaddr to initialize qsock->path).

Thus the check for qsock->path is excessive and can be read wrong, assuming
that other options possible, leading to warnings from clang static analyzer.
2021-12-01 18:33:29 +03:00
Sergey Kandaurov
0d8ddc57e8 QUIC: ngx_quic_send_alert() callback moved to its place. 2021-11-30 14:30:59 +03:00
Sergey Kandaurov
a9546f2161 QUIC: simplified ngx_quic_send_alert() callback.
Removed sending CLOSE_CONNECTION directly to avoid duplicate frames,
since it is sent later again in SSL_do_handshake() error handling.
As such, removed redundant settings of error fields set elsewhere.
While here, improved debug message.
2021-11-30 14:30:59 +03:00
Vladimir Homutov
5ddebcaaff QUIC: removed unnecessary closing of active/backup sockets.
All open sockets are stored in a queue.  There is no need to close some
of them separately.  If it happens that active and backup point to same
socket, double close may happen (leading to possible segfault).
2021-11-18 14:33:21 +03:00
Vladimir Homutov
70907fdbe0 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>
2021-11-29 11:51:14 +03:00
Vladimir Homutov
1c29db5dba QUIC: refactored multiple QUIC packets handling.
Single UDP datagram may contain multiple QUIC datagrams.  In order to
facilitate handling of such cases, 'first' flag in the ngx_quic_header_t
structure is introduced.
2021-11-29 11:49:09 +03:00
Vladimir Homutov
2730e38d8b QUIC: fixed handling of RETIRE_CONNECTION_ID frame.
Previously, the retired socket was not closed if it didn't match
active or backup.

New sockets could not be created (due to count limit), since retired socket
was not closed before calling ngx_quic_create_sockets().

When replacing retired socket, new socket is only requested after closing
old one, to avoid hitting the limit on the number of active connection ids.

Together with added restrictions, this fixes an issue when a current socket
could be closed during migration, recreated and erroneously reused leading
to null pointer dereference.
2021-11-18 14:19:36 +03:00
Vladimir Homutov
64488e4e6f QUIC: additional checks for the RETIRE_CONNECTION_ID frame. 2021-11-18 14:19:31 +03:00
Roman Arutyunyan
52021bf4a0 QUIC: handle DATA_BLOCKED frame from client.
Previously the frame was not handled and connection was closed with an error.
Now, after receiving this frame, global flow control is updated and new
flow control credit is sent to client.
2021-11-17 23:07:51 +03:00
Roman Arutyunyan
75c17858cc QUIC: update stream flow control credit on STREAM_DATA_BLOCKED.
Previously, after receiving STREAM_DATA_BLOCKED, current flow control limit
was sent to client.  Now, if the limit can be updated to the full window size,
it is updated and the new value is sent to client, otherwise nothing is sent.

The change lets client update flow control credit on demand.  Also, it saves
traffic by not sending MAX_STREAM_DATA with the same value twice.
2021-11-17 23:07:38 +03:00
Roman Arutyunyan
7bd866a9a5 HTTP/3: fixed compilation with QUIC, but without HTTP/3. 2021-11-17 18:49:48 +03:00
Roman Arutyunyan
07a983f8df QUIC: reject streams which we could not create.
The reasons why a stream may not be created by server currently include hitting
worker_connections limit and memory allocation error.  Previously in these
cases the entire QUIC connection was closed and all its streams were shut down.
Now the new stream is rejected and existing streams continue working.

To reject an HTTP/3 request stream, RESET_STREAM and STOP_SENDING with
H3_REQUEST_REJECTED error code are sent to client.  HTTP/3 uni streams and
Stream streams are not rejected.
2021-11-11 19:07:00 +03:00
Sergey Kandaurov
8d62635537 QUIC: stop processing new client streams at the closing state. 2021-11-12 16:29:07 +03:00
Sergey Kandaurov
b14bef9520 SSL: $ssl_curve (ticket #2135).
The variable contains a negotiated curve used for the handshake key
exchange process.  Known curves are listed by their names, unknown
ones are shown in hex.

Note that for resumed sessions in TLSv1.2 and older protocols,
$ssl_curve contains the curve used during the initial handshake,
while in TLSv1.3 it contains the curve used during the session
resumption (see the SSL_get_negotiated_group manual page for
details).

The variable is only meaningful when using OpenSSL 3.0 and above.
With older versions the variable is empty.
2021-11-01 18:09:34 +03:00
Sergey Kandaurov
3771c70da7 Version bump. 2021-11-23 12:52:43 +03:00
Maxim Dounin
a1459645ce release-1.21.4 tag 2021-11-02 17:49:22 +03:00
Maxim Dounin
65d47e2d65 nginx-1.21.4-RELEASE 2021-11-02 17:49:22 +03:00
Maxim Dounin
d828e18761 Changed ngx_chain_update_chains() to test tag first (ticket #2248).
Without this change, aio used with HTTP/2 can result in connection hang,
as observed with "aio threads; aio_write on;" and proxying (ticket #2248).

The problem is that HTTP/2 updates buffers outside of the output filters
(notably, marks them as sent), and then posts a write event to call
output filters.  If a filter does not call the next one for some reason
(for example, because of an AIO operation in progress), this might
result in a state when the owner of a buffer already called
ngx_chain_update_chains() and can reuse the buffer, while the same buffer
is still sitting in the busy chain of some other filter.

In the particular case a buffer was sitting in output chain's ctx->busy,
and was reused by event pipe.  Output chain's ctx->busy was permanently
blocked by it, and this resulted in connection hang.

Fix is to change ngx_chain_update_chains() to skip buffers from other
modules unconditionally, without trying to wait for these buffers to
become empty.
2021-10-30 02:39:19 +03:00
Maxim Dounin
a1593eb4d6 Changed default value of sendfile_max_chunk to 2m.
The "sendfile_max_chunk" directive is important to prevent worker
monopolization by fast connections.  The 2m value implies maximum 200ms
delay with 100 Mbps links, 20ms delay with 1 Gbps links, and 2ms on
10 Gbps links.  It also seems to be a good value for disks.
2021-10-29 20:21:57 +03:00
Maxim Dounin
79ea33d679 Upstream: sendfile_max_chunk support.
Previously, connections to upstream servers used sendfile() if it was
enabled, but never honored sendfile_max_chunk.  This might result
in worker monopolization for a long time if large request bodies
are allowed.
2021-10-29 20:21:54 +03:00