Commit Graph

6575 Commits

Author SHA1 Message Date
Vladimir Homutov
264dd955cb QUIC: fixed macro style. 2022-01-25 15:48:05 +03:00
Roman Arutyunyan
c403822674 QUIC: fixed chain returned from ngx_quic_write_chain().
Previously, when input ended on a QUIC buffer boundary, input chain was not
advanced to the next buffer.  As a result, ngx_quic_write_chain() returned
a chain with an empty buffer instead of NULL.  This broke HTTP write filter,
preventing it from closing the HTTP request and eventually timing out.

Now input chain is always advanced to a buffer that has data, before checking
QUIC buffer boundary condition.
2022-01-25 09:45:50 +03:00
Vladimir Homutov
a0aa287d13 QUIC: removed stale declaration.
The ngx_quic_get_unconnected_socket() was removed in 1e2f4e9c8195.
2022-01-21 11:41:39 +03:00
Vladimir Homutov
67b9f081d0 QUIC: avoid logging error in case of version negotiation.
Previously, "early error" message was logged in this case.
2022-01-23 21:29:36 +03:00
Vladimir Homutov
a816af6e1b QUIC: additional limit for probing packets.
RFC 9000, 9.3.  Responding to Connection Migration:
    An endpoint only changes the address to which it sends packets in
    response to the highest-numbered non-probing packet.

The patch extends this requirement to probing packets.  Although it may
seem excessive, it helps with mitigation of reply attacks (when an off-path
attacker has copied packet with PATH_CHALLENGE and uses different
addresses to exhaust available connection ids).
2022-01-20 22:00:25 +03:00
Pavel Pautov
950390108c Core: simplify reader lock release. 2022-01-19 17:37:34 -08:00
Vladimir Homutov
8a4a267d74 QUIC: reworked migration handling.
The quic connection now holds active, backup and probe paths instead
of sockets.  The number of migration paths is now limited and cannot
be inflated by a bad client or an attacker.

The client id is now associated with path rather than socket. This allows
to simplify processing of output and connection ids handling.

New migration abandons any previously started migrations.  This allows to
free consumed client ids and request new for use in future migrations and
make progress in case when connection id limit is hit during migration.

A path now can be revalidated without losing its state.

The patch also fixes various issues with NAT rebinding case handling:
    - paths are now validated (previously, there was no validation
      and paths were left in limited state)
    - attempt to reuse id on different path is now again verified
      (this was broken in 40445fc7c403)
    - former path is now validated in case of apparent migration
2022-01-19 22:39:24 +03:00
Vladimir Homutov
1f97aa71ec QUIC: the "quic_active_connection_id_limit" directive.
The directive sets corresponding transport parameter and limits number of
created client ids.
2022-01-18 12:49:55 +03:00
Sergey Kandaurov
429150c1fa SSL: free pkey on SSL_CTX_set0_tmp_dh_pkey() failure.
The behaviour was changed in OpenSSL 3.0.1:
https://git.openssl.org/?p=openssl.git;a=commitdiff;h=bf17b7b
2022-01-17 17:05:12 +03:00
Roman Arutyunyan
8a67a56091 QUIC: introduced function ngx_quic_split_chain().
The function splits a buffer at given offset.  The function is now
called from ngx_quic_read_chain() and ngx_quic_write_chain(), which
simplifies both functions.
2022-01-17 14:39:04 +03:00
Roman Arutyunyan
6844eeb9c9 QUIC: fixed format specifier after 3789f4a56d65. 2022-01-16 00:28:13 +03:00
Roman Arutyunyan
2ba20e3451 QUIC: return written size from ngx_quic_write_chain().
This allows to escape calculating it before calling the function.
2022-01-13 11:34:42 +03:00
Sergey Kandaurov
bd4a26c164 QUIC: removed ngx_send_lowat() check for QUIC connections.
After 9ae239d2547d, ngx_quic_handle_write_event() no longer runs into
ngx_send_lowat() for QUIC connections, so the check became excessive.
It is assumed that external modules operating with SO_SNDLOWAT
(I'm not aware of any) should do this check on their own.
2022-01-13 15:57:21 +03:00
Sergey Kandaurov
a7a3a8cc17 HTTP/3: removed useless warning regarding OpenSSL library.
After 0e6528551f26, it became impossible to run into this path.
2022-01-13 15:57:15 +03:00
Roman Arutyunyan
35fc2eb247 QUIC: fixed handling stream input buffers.
Previously, ngx_quic_write_chain() treated each input buffer as a memory
buffer, which is not always the case.  Special buffers were not skipped, which
is especially important when hitting the input byte limit.

The issue manifested itself with ngx_quic_write_chain() returning a non-empty
chain consisting of a special last_buf buffer when called from QUIC stream
send_chain().  In order for this to happen, input byte limit should be equal to
the chain length, and the input chain should end with an empty last_buf buffer.
An easy way to achieve this is the following:

  location /empty {
      return 200;
  }

When this non-empty chain was returned from send_chain(), it signalled to the
caller that input was blocked, while in fact it wasn't.  This prevented HTTP
request from finalization, which prevented QUIC from sending STREAM FIN to
the client.  The QUIC stream was then reset after a timeout.

Now special buffers are skipped and send_chain() returns NULL in the case
above, which signals to the caller a successful operation.

Also, original byte limit is now passed to ngx_quic_write_chain() from
send_chain() instead of actual chain length to make sure it's never zero.
2022-01-13 11:23:53 +03:00
Roman Arutyunyan
a6120a9bc5 QUIC: fixed handling STREAM FIN.
Previously, when a STREAM FIN frame with no data bytes was received after all
prior stream data were already read by the application layer, the frame was
ignored and eof was not reported to the application.
2022-01-11 18:57:02 +03:00
Roman Arutyunyan
38cfe35779 HTTP/3: set c->error on read error in ngx_http_test_reading().
Similar to other error/eof cases.
2022-01-12 11:57:46 +03:00
Roman Arutyunyan
5ab94d4219 HTTP/3: simplified code. 2022-01-12 11:57:06 +03:00
Roman Arutyunyan
109166e4fa QUIC: modified HTTP version test.
The new condition produces smaller diff to the default branch and is similar to
HTTP/2 case.
2022-01-12 11:54:39 +03:00
Maxim Dounin
22d4ff08bb Avoid sending "Connection: keep-alive" when shutting down.
When a worker process is shutting down, keepalive is not used: this is checked
before the ngx_http_set_keepalive() call in ngx_http_finalize_connection().
Yet the "Connection: keep-alive" header was still sent, even if we know that
the worker process is shutting down, potentially resulting in additional
requests being sent to the connection which is going to be closed anyway.
While clients are expected to be able to handle asynchronous close events
(see ticket #1022), it is certainly possible to send the "Connection: close"
header instead, informing the client that the connection is going to be closed
and potentially saving some unneeded work.

With this change, we additionally check for worker process shutdown just
before sending response headers, and disable keepalive accordingly.
2022-01-11 02:23:49 +03:00
Sergey Kandaurov
b1356ade07 HTTP/3: improved processing of multiple Cookie field lines.
As per draft-ietf-quic-http, 4.1.1.2, and similar to HTTP/2 specification,
they ought to be concatenated.  This closely follows ngx_http_v2_module.
2021-12-30 12:59:32 +03:00
Maxim Dounin
96c342e560 Events: fixed balancing between workers with EPOLLEXCLUSIVE.
Linux with EPOLLEXCLUSIVE usually notifies only the process which was first
to add the listening socket to the epoll instance.  As a result most of the
connections are handled by the first worker process (ticket #2285).  To fix
this, we re-add the socket periodically, so other workers will get a chance
to accept connections.
2021-12-30 01:08:46 +03:00
Maxim Dounin
6147266217 Version bump. 2021-12-29 22:59:53 +03:00
Roman Arutyunyan
7f0fdd4e14 Style. 2021-12-29 15:33:51 +03:00
Sergey Kandaurov
f3363a8dbe Merged with the default branch. 2021-12-29 15:17:26 +03:00
Maxim Dounin
1f01183b9e Support for sendfile(SF_NOCACHE).
The SF_NOCACHE flag, introduced in FreeBSD 11 along with the new non-blocking
sendfile() implementation by glebius@, makes it possible to use sendfile()
along with the "directio" directive.
2021-12-27 19:49:26 +03:00
Maxim Dounin
2a00e6141f SSL: SSL_sendfile(SF_NODISKIO) support. 2021-12-27 19:48:42 +03:00
Maxim Dounin
20c35434ef Simplified sendfile(SF_NODISKIO) usage.
Starting with FreeBSD 11, there is no need to use AIO operations to preload
data into cache for sendfile(SF_NODISKIO) to work.  Instead, sendfile()
handles non-blocking loading data from disk by itself.  It still can, however,
return EBUSY if a page is already being loaded (for example, by a different
process).  If this happens, we now post an event for the next event loop
iteration, so sendfile() is retried "after a short period", as manpage
recommends.

The limit of the number of EBUSY tolerated without any progress is preserved,
but now it does not result in an alert, since on an idle system event loop
iteration might be very short and EBUSY can happen many times in a row.
Instead, SF_NODISKIO is simply disabled for one call once the limit is
reached.

With this change, sendfile(SF_NODISKIO) is now used automatically as long as
sendfile() is enabled, and no longer requires "aio on;".
2021-12-27 19:48:33 +03:00
Maxim Dounin
f0a5ce136d Removed "aio sendfile", deprecated since 1.7.11. 2021-12-27 19:47:05 +03:00
Vladimir Homutov
fa21bf0cc7 QUIC: got rid of ngx_quic_create_temp_socket().
It was mostly copy of the ngx_quic_listen().  Now ngx_quic_listen() no
longer generates server id and increments seqnum.  Instead, the server
id is generated when the socket is created.

The ngx_quic_alloc_socket() function is renamed to ngx_quic_create_socket().
2021-12-27 13:49:56 +03:00
Ruslan Ermilov
05a32b5ec4 Fixed a mismerge in 5c86189a1c1b. 2021-12-28 15:01:02 +03:00
Roman Arutyunyan
3662e0c83b QUIC: renamed input handling functions.
Now these functions have names ngx_quic_handle_XXX():

  - ngx_quic_process_stateless_reset() -> ngx_quic_handle_stateless_reset()
  - ngx_quic_input() -> ngx_quic_handle_datagram()
  - ngx_quic_process_packet() -> ngx_quic_handle_packet()
  - ngx_quic_process_payload() -> ngx_quic_handle_payload()
2021-12-27 16:15:28 +03:00
Roman Arutyunyan
cf96432910 QUIC: fixed format specifier after 6ccf3867959a. 2021-12-28 13:50:01 +03:00
Vladimir Homutov
bef80e70f6 QUIC: fixed config test with bpf (ticket #2292).
The SO_REUSEPORT socket option is not set during configuration testing,
thus making the further module initialization impossible and meaningless.
2021-12-28 13:24:58 +03:00
Maxim Dounin
d5f1f169bc Core: added NGX_REGEX_MULTILINE for 3rd party modules.
Notably, NAXSI is known to misuse ngx_regex_compile() with rc.options set
to PCRE_CASELESS | PCRE_MULTILINE.  With PCRE2 support, and notably binary
compatibility changes, it is no longer possible to set PCRE[2]_MULTILINE
option without using proper interface.  To facilitate correct usage,
this change adds the NGX_REGEX_MULTILINE option.
2021-12-25 01:07:18 +03:00
Maxim Dounin
931acbf5bc PCRE2 and PCRE binary compatibility.
With this change, dynamic modules using nginx regex interface can be used
regardless of the variant of the PCRE library nginx was compiled with.

If a module is compiled with different PCRE library variant, in case of
ngx_regex_exec() errors it will report wrong function name in error
messages.  This is believed to be tolerable, given that fixing this will
require interface changes.
2021-12-25 01:07:16 +03:00
Maxim Dounin
c6fec0b027 PCRE2 library support.
The PCRE2 library is now used by default if found, instead of the
original PCRE library.  If needed for some reason, this can be disabled
with the --without-pcre2 configure option.

To make it possible to specify paths to the library and include files
via --with-cc-opt / --with-ld-opt, the library is first tested without
any additional paths and options.  If this fails, the pcre2-config script
is used.

Similarly to the original PCRE library, it is now possible to build PCRE2
from sources with nginx configure, by using the --with-pcre= option.
It automatically detects if PCRE or PCRE2 sources are provided.

Note that compiling PCRE2 10.33 and later requires inttypes.h.  When
compiling on Windows with MSVC, inttypes.h is only available starting
with MSVC 2013.  In older versions some replacement needs to be provided
("echo '#include <stdint.h>' > pcre2-10.xx/src/inttypes.h" is good enough
for MSVC 2010).

The interface on nginx side remains unchanged.
2021-12-25 01:07:15 +03:00
Maxim Dounin
28f8caac37 Core: ngx_regex.c style cleanup.
Notably, ngx_pcre_pool and ngx_pcre_studies are renamed to ngx_regex_pool
and ngx_regex_studies, respectively.
2021-12-25 01:07:12 +03:00
Maxim Dounin
09268f58b4 Core: fixed ngx_pcre_studies cleanup.
If a configuration parsing fails for some reason, ngx_regex_module_init()
is not called, and ngx_pcre_studies remained set despite the fact that
the pool it was allocated from is already freed.  This might result in
a segmentation fault during runtime regular expression compilation, such
as in SSI, for example, in the single process mode, or if a worker process
died and was respawned from a master process in such an inconsistent state.

Fix is to clear ngx_pcre_studies from the pool cleanup handler (which is
anyway used to free JIT-compiled patterns).
2021-12-25 01:07:10 +03:00
Roman Arutyunyan
cd278da5e7 QUIC: refactored buffer allocation, spliting and freeing.
Previously, buffer lists was used to track used buffers.  Now reference
counter is used instead.  The new implementation is simpler and faster with
many buffer clones.
2021-12-24 18:39:22 +03:00
Ruslan Ermilov
363505e806 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
Roman Arutyunyan
703be8c8f6 QUIC: removed ngx_quic_copy_chain().
The function is unused.
2021-12-16 17:07:11 +03:00
Roman Arutyunyan
4d79f94221 QUIC: renamed buffer-related functions.
ngx_quic_alloc_buf() -> ngx_quic_alloc_chain(),
ngx_quic_free_bufs() -> ngx_quic_free_chain(),
ngx_quic_trim_bufs() -> ngx_quic_trim_chain()
2021-12-16 17:06:35 +03:00
Roman Arutyunyan
baea97bc54 QUIC: refactored ngx_quic_order_bufs() and ngx_quic_split_bufs().
They are replaced with ngx_quic_write_chain() and ngx_quic_read_chain().
These functions represent the API to data buffering.

The first function adds data of given size at given offset to the buffer.
Now it returns the unwritten part of the chain similar to c->send_chain().

The second function returns data of given size from the beginning of the buffer.
Its second argument and return value are swapped compared to
ngx_quic_split_bufs() to better match ngx_quic_write_chain().

Added, returned and stored data are regular ngx_chain_t/ngx_buf_t chains.
Missing data is marked with b->sync flag.

The functions are now used in both send and recv data chains in QUIC streams.
2021-12-24 18:17:23 +03:00
Roman Arutyunyan
97b34a01e2 QUIC: avoid excessive buffer allocations in stream output.
Previously, when a few bytes were send to a QUIC stream by the application, a
4K buffer was allocated for these bytes.  Then a STREAM frame was created and
that entire buffer was used as data for that frame.  The frame with the buffer
were in use up until the frame was acked by client.  Meanwhile, when more
bytes were send to the stream, more buffers were allocated and assigned as
data to newer STREAM frames.  In this scenario most buffer memory is unused.

Now the unused part of the stream output buffer is available for further
stream output while earlier parts of the buffer are waiting to be acked.
This is achieved by splitting the output buffer.
2021-12-24 18:13:51 +03:00
Vladimir Homutov
541ec50c42 QUIC: got rid of excessive "qsock" argument in ngx_quic_output.c.
The output is always sent to the active path, which is stored in the
quic connection.  There is no need to pass it in arguments.

When output has to be send to to a specific path (in rare cases, such as
path probing), a separate method exists (ngx_quic_frame_sendto()).
2021-12-27 13:52:57 +03:00
Vladimir Homutov
cb273ddf91 QUIC: refactored ngx_quic_validate_path().
The function now accepts path argument, as suggested by the name. Socket is
not really needed inside.
2021-12-16 11:49:08 +03:00
Vladimir Homutov
93230cd8cf QUIC: added missing check for backup path existence. 2021-12-16 11:42:28 +03:00
Ruslan Ermilov
fa4da05854 Merged with the default branch. 2021-12-24 15:53:59 +03:00
Roman Arutyunyan
3341a85076 QUIC: added path limiting function ngx_quic_path_limit(). 2021-12-14 16:24:20 +03:00
Vladimir Homutov
10fd8be86d 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
a31745499b 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
6e7f192804 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
6ea39f03ae 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
83e92a2edd 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
2361e98a34 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
59312ddac1 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
Vladimir Homutov
3ab900cbd9 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
b61447d436 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
702a0986f3 QUIC: fixed e06283038ec8 mis-merge.
The NGX_HTTP_QUIC macro was removed in 33226ac61076.
2021-12-09 11:15:25 +03:00
Sergey Kandaurov
dea9a208c3 HTTP/3: cleanup after "listen .. quic" removal in be08b858086a. 2021-12-08 17:04:56 +03:00
Sergey Kandaurov
a42a62fc58 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
9860a82b19 HTTP/3: avoid sending stream cancellation for pushed streams. 2021-12-07 15:49:30 +03:00
Sergey Kandaurov
1bd3cae959 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
d1bc1da950 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
0791b50880 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
835854520a 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
d84c1f7885 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
731915a0c5 HTTP/3: merged ngx_http_quic_module into ngx_http_v3_module. 2021-12-06 13:02:36 +03:00
Vladimir Homutov
ea55dbccb2 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
e6949057ea QUIC: logging of CRYPTO frame payload under NGX_QUIC_DEBUG_FRAMES. 2021-12-02 13:59:56 +03:00
Sergey Kandaurov
7e7e552a10 HTTP/3: adjusted ALPN macro names to align with 61abb35bb8cf. 2021-12-02 13:59:09 +03:00
Vladimir Homutov
468641cbc3 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
a981efe6e8 QUIC: ngx_quic_send_alert() callback moved to its place. 2021-11-30 14:30:59 +03:00
Sergey Kandaurov
ac851d7f69 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
0de6a1ebb4 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
82b4912a8e 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
b8aa869a6f 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
e165526e43 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
1688afd955 QUIC: additional checks for the RETIRE_CONNECTION_ID frame. 2021-11-18 14:19:31 +03:00
Roman Arutyunyan
d4add97845 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
4bb4792907 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
bfa2d1d599 HTTP/3: fixed compilation with QUIC, but without HTTP/3. 2021-11-17 18:49:48 +03:00
Roman Arutyunyan
50dd9ba7e8 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
54655cebbb QUIC: stop processing new client streams at the closing state. 2021-11-12 16:29:07 +03:00
Sergey Kandaurov
5c32499644 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
f3915c33e7 Version bump. 2021-11-23 12:52:43 +03:00
Maxim Dounin
2c8dd1c33e 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
5636e7f7b4 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
b3b368184b 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
Maxim Dounin
6b0d773fbd Fixed sendfile() limit handling on Linux.
On Linux starting with 2.6.16, sendfile() silently limits all operations
to MAX_RW_COUNT, defined as (INT_MAX & PAGE_MASK).  This incorrectly
triggered the interrupt check, and resulted in 0-sized writev() on the
next loop iteration.

Fix is to make sure the limit is always checked, so we will return from
the loop if the limit is already reached even if number of bytes sent is
not exactly equal to the number of bytes we've tried to send.
2021-10-29 20:21:51 +03:00
Maxim Dounin
00f4be1ce4 Simplified sendfile_max_chunk handling.
Previously, it was checked that sendfile_max_chunk was enabled and
almost whole sendfile_max_chunk was sent (see e67ef50c3176), to avoid
delaying connections where sendfile_max_chunk wasn't reached (for example,
when sending responses smaller than sendfile_max_chunk).  Now we instead
check if there are unsent data, and the connection is still ready for writing.
Additionally we also check c->write->delayed to ignore connections already
delayed by limit_rate.

This approach is believed to be more robust, and correctly handles
not only sendfile_max_chunk, but also internal limits of c->send_chain(),
such as sendfile() maximum supported length (ticket #1870).
2021-10-29 20:21:48 +03:00
Maxim Dounin
f3fdc4c96f Switched to using posted next events after sendfile_max_chunk.
Previously, 1 millisecond delay was used instead.  In certain edge cases
this might result in noticeable performance degradation though, notably on
Linux with typical CONFIG_HZ=250 (so 1ms delay becomes 4ms),
sendfile_max_chunk 2m, and link speed above 2.5 Gbps.

Using posted next events removes the artificial delay and makes processing
fast in all cases.
2021-10-29 20:21:43 +03:00
Roman Arutyunyan
7927071ee2 Mp4: mp4_start_key_frame directive.
The directive enables including all frames from start time to the most recent
key frame in the result.  Those frames are removed from presentation timeline
using mp4 edit lists.

Edit lists are currently supported by popular players and browsers such as
Chrome, Safari, QuickTime and ffmpeg.  Among those not supporting them properly
is Firefox[1].

Based on a patch by Tracey Jaquith, Internet Archive.

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1735300
2021-10-28 14:14:25 +03:00
Roman Arutyunyan
27cdfe30f7 Mp4: added ngx_http_mp4_update_mdhd_atom() function.
The function updates the duration field of mdhd atom.  Previously it was
updated in ngx_http_mp4_read_mdhd_atom().  The change makes it possible to
alter track duration as a result of processing track frames.
2021-10-28 13:11:31 +03:00
Roman Arutyunyan
5c99f43e6f HTTP/3: send Stream Cancellation instruction.
As per quic-qpack-21:

   When a stream is reset or reading is abandoned, the decoder emits a
   Stream Cancellation instruction.

Previously the instruction was not sent.  Now it's sent when closing QUIC
stream connection if dynamic table capacity is non-zero and eof was not
received from client.  The latter condition means that a trailers section
may still be on its way from client and the stream needs to be cancelled.
2021-10-18 14:48:11 +03:00
Roman Arutyunyan
a6fb8fe850 HTTP/3: allowed QUIC stream connection reuse.
A QUIC stream connection is treated as reusable until first bytes of request
arrive, which is also when the request object is now allocated.  A connection
closed as a result of draining, is reset with the error code
H3_REQUEST_REJECTED.  Such behavior is allowed by quic-http-34:

   Once a request stream has been opened, the request MAY be cancelled
   by either endpoint. Clients cancel requests if the response is no
   longer of interest; servers cancel requests if they are unable to or
   choose not to respond.

   When the server cancels a request without performing any application
   processing, the request is considered "rejected."  The server SHOULD
   abort its response stream with the error code H3_REQUEST_REJECTED.

   The client can treat requests rejected by the server as though they had
   never been sent at all, thereby allowing them to be retried later.
2021-10-18 15:47:06 +03:00
Roman Arutyunyan
6118ec73cf HTTP/3: adjusted QUIC connection finalization.
When an HTTP/3 function returns an error in context of a QUIC stream, it's
this function's responsibility now to finalize the entire QUIC connection
with the right code, if required.  Previously, QUIC connection finalization
could be done both outside and inside such functions.  The new rule follows
a similar rule for logging, leads to cleaner code, and allows to provide more
details about the error.

While here, a few error cases are no longer treated as fatal and QUIC connection
is no longer finalized in these cases.  A few other cases now lead to
stream reset instead of connection finalization.
2021-10-18 15:22:33 +03:00
Vladimir Homutov
1562200066 QUIC: fixed PATH_RESPONSE frame expansion.
The PATH_RESPONSE frame must be expanded to 1200, except the case
when anti-amplification limit is in effect, i.e. on unvalidated paths.

Previously, the anti-amplification limit was always applied.
2021-11-11 15:15:07 +03:00
Vladimir Homutov
62b2eea0fe QUIC: removed ngx_quic_error_text() declaration.
This is a leftover from cab3b7a070ef.
2021-11-10 14:36:36 +03:00
Vladimir Homutov
a3163fa4b2 QUIC: fixed GSO packets count.
Thanks to Andrey Kolyshkin <a.kolyshkin@corp.vk.com>
2021-11-09 21:17:05 +03:00
Vladimir Homutov
6f9f8bf96e QUIC: removed dead code.
The function is no longer used since b3d9e57d0f62.
2021-11-10 13:49:01 +03:00
Vladimir Homutov
df22336bfa QUIC: converted client_tp_done to bitfield. 2021-11-08 15:41:12 +03:00
Vladimir Homutov
9ca3a02e68 QUIC: fixed removal of unused client IDs.
If client ID was never used, its refcount is zero.  To keep things simple,
the ngx_quic_unref_client_id() function is now aware of such IDs.

If client ID was used, the ngx_quic_replace_retired_client_id() function
is supposed to find all users and unref the ID, thus ngx_quic_unref_client_id()
should not be called after it.
2021-10-13 14:48:33 +03:00
Vladimir Homutov
0572c2a69f QUIC: connections with wrong ALPN protocols are now rejected.
Previously, it was not enforced in the stream module.
Now, since b9e02e9b2f1d it is possible to specify protocols.

Since ALPN is always required, the 'require_alpn' setting is now obsolete.
2021-11-03 13:36:21 +03:00
Vladimir Homutov
5f9c4e15a3 QUIC: refactored packet creation.
The "min" and "max" arguments refer to UDP datagram size.  Generating payload
requires to account properly for header size, which is variable and depends on
payload size and packet number.
2021-10-07 13:48:29 +03:00
Vladimir Homutov
151985c931 QUIC: removed unused argument in ngx_quic_create_short_header(). 2021-10-07 12:24:47 +03:00
Vladimir Homutov
47caa66489 QUIC: added function to initialize packet. 2021-09-30 12:02:29 +03:00
Vladimir Homutov
dbb59fba8c QUIC: fixed processing of minimum packet size.
If packet needs to be expanded (for example Initial to 1200 bytes),
but path limit is less, such packet should not be created/sent.
2021-10-22 12:59:44 +03:00
Vladimir Homutov
f5d0c6db67 QUIC: added shutdown support in stream proxy. 2021-09-23 16:25:49 +03:00
Sergey Kandaurov
bbd05ae252 Merged with the default branch. 2021-11-03 11:22:07 +03:00
Sergey Kandaurov
8f8cb92e92 QUIC: style. 2021-10-26 18:05:57 +03:00
Sergey Kandaurov
01d27365c6 QUIC: speeding up processing 0-RTT.
After fe919fd63b0b, processing QUIC streams was postponed until after handshake
completion, which means that 0-RTT is effectively off.  With ssl_ocsp enabled,
it could be further delayed.  This differs from how OCSP validation works with
SSL_read_early_data().  With this change, processing QUIC streams is unlocked
when obtaining 0-RTT secret.
2021-10-26 17:43:10 +03:00
Sergey Kandaurov
2f754d5dcf QUIC: refactored OCSP validation in preparation for 0-RTT support. 2021-10-26 17:43:10 +03:00
Vladimir Homutov
12bda330d9 QUIC: switched to integer arithmetic in rtt calculations.
RFC 9002 uses constants implying effective implementation,
i.e. using bit shift operations instead of floating point.
2021-10-19 14:32:50 +03:00
Vladimir Homutov
0cd45dea76 QUIC: optimized ack range processing.
The sent queue is sorted by packet number.  It is possible to avoid
traversing full queue while handling ack ranges.  It makes sense to
start traversing from the queue head (i.e. check oldest packets first).
2021-10-15 12:26:42 +03:00
Roman Arutyunyan
da28a4c626 QUIC: limited the total number of frames.
Exceeding 10000 allocated frames is considered a flood.
2021-10-13 14:46:51 +03:00
Roman Arutyunyan
6e58593a59 QUIC: traffic-based flood detection.
With this patch, all traffic over a QUIC connection is compared to traffic
over QUIC streams.  As long as total traffic is many times larger than stream
traffic, we consider this to be a flood.
2021-10-13 14:41:46 +03:00
Roman Arutyunyan
434f11bf3f 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.
2021-10-07 13:22:42 +03:00
Roman Arutyunyan
0c33e484a4 HTTP/3: fixed request length calculation.
Previously, when request was blocked, r->request_length was not updated.
2021-10-06 14:51:16 +03:00
Roman Arutyunyan
ec86cf18fa HTTP/3: removed client-side encoder support.
Dynamic tables are not used when generating responses anyway.
2021-10-06 14:48:59 +03:00
Martin Duke
7b12abb0a8 QUIC: attempt decrypt before checking for stateless reset.
Checking the reset after encryption avoids false positives.  More importantly,
it avoids the check entirely in the usual case where decryption succeeds.

RFC 9000, 10.3.1  Detecting a Stateless Reset

    Endpoints MAY skip this check if any packet from a datagram is
    successfully processed.
2021-10-12 11:57:50 +03:00
Martin Duke
5e37df0bf4 QUIC: Check if CID has been used in stateless reset check
Section 10.3.1 of RFC9000 requires this check.
2021-10-12 11:56:49 +03:00
Roman Arutyunyan
010f974e44 QUIC: send RESET_STREAM in response to STOP_SENDING.
As per RFC 9000:

   An endpoint that receives a STOP_SENDING frame MUST send a RESET_STREAM
   frame if the stream is in the "Ready" or "Send" state.

   An endpoint SHOULD copy the error code from the STOP_SENDING frame to
   the RESET_STREAM frame it sends, but it can use any application error code.
2021-09-21 16:24:33 +03:00
Roman Arutyunyan
22f2dc2a87 QUIC: reset stream only once. 2021-09-22 14:02:56 +03:00
Roman Arutyunyan
38d56f4ccd HTTP/3: reset streams with incomplete responses or timeouts.
This prevents client from closing the QUIC connection due to response parse
error.
2021-09-27 17:08:48 +03:00
Roman Arutyunyan
b6b2a45fb6 Added r->response_sent flag.
The flag indicates that the entire response was sent to the socket up to the
last_buf flag.  The flag is only usable for protocol implementations that call
ngx_http_write_filter() from header filter, such as HTTP/1.x and HTTP/3.
2021-09-30 17:14:42 +03:00
Sergey Kandaurov
3c31d3f421 Stream: fixed segfault when using SSL certificates with variables.
Similar to the previous change, a segmentation fault occurres when evaluating
SSL certificates on a QUIC connection due to an uninitialized stream session.
The fix is to adjust initializing the QUIC part of a connection until after
it has session and variables initialized.

Similarly, this appends logging error context for QUIC connections:
- client 127.0.0.1:54749 connected to 127.0.0.1:8880 while handling frames
- quic client timed out (60: Operation timed out) while handling quic input
2021-09-29 15:06:28 +03:00
Sergey Kandaurov
dab6035d68 HTTP/3: fixed segfault when using SSL certificates with variables.
A QUIC connection doesn't have c->log->data and friends initialized to sensible
values.  Yet, a request can be created in the certificate callback with such an
assumption, which leads to a segmentation fault due to null pointer dereference
in ngx_http_free_request().  The fix is to adjust initializing the QUIC part of
a connection such that it has all of that in place.

Further, this appends logging error context for unsuccessful QUIC handshakes:
- cannot load certificate .. while handling frames
- SSL_do_handshake() failed .. while sending frames
2021-09-29 15:01:59 +03:00
Sergey Kandaurov
1ea6f35fbf Stream: detect "listen .. quic" without TLSv1.3. 2021-09-29 15:01:56 +03:00
Sergey Kandaurov
2765b63216 Fixed mismerge of ssl_reject_handshake in 71b7453fb11f.
In particular, this fixes rejecting "listen .. quic|http3" configurations
without TLSv1.3 configured.
2021-09-29 15:01:53 +03:00
Sergey Kandaurov
4d92aa7957 HTTP/3: fixed server push after ea9b645472b5.
Unlike in HTTP/2, both "host" and ":authority" reside in r->headers_in.server.
2021-09-27 17:42:53 +03:00
Sergey Kandaurov
a5b5b6ca0f QUIC: moved a variable initialization near to its use.
This tends to produce slightly more optimal code with pos == NULL
when built with Clang on low optimization levels.

Spotted by Ruslan Ermilov.
2021-09-27 15:38:55 +03:00
Ruslan Ermilov
8ce1c2c7e9 Configure: check for QUIC 0-RTT support at compile time. 2021-09-27 10:10:37 +03:00
Sergey Kandaurov
2cd173d450 HTTP/3: fixed null pointer dereference with server push.
See details for HTTP/2 fix in 8b0553239592 for a complete description.
2021-09-22 14:10:43 +03:00
Roman Arutyunyan
08dcf62f5b HTTP/3: fixed ngx_stat_active counter.
Previously the counter was not incremented for HTTP/3 streams, but still
decremented in ngx_http_close_connection().  There are two solutions here, one
is to increment the counter for HTTP/3 streams, and the other one is not to
decrement the counter for HTTP/3 streams.  The latter solution looks
inconsistent with ngx_stat_reading/ngx_stat_writing, which are incremented on a
per-request basis.  The change adds ngx_stat_active increment for HTTP/3
request and push streams.
2021-09-22 14:08:21 +03:00
Roman Arutyunyan
3ae914c837 HTTP/3: fixed pushed request finalization in case of error.
Previously request could be finalized twice.  For example, this could happen
if "Host" header was invalid.
2021-09-17 15:28:31 +03:00
Sergey Kandaurov
4e2e70b16c QUIC: set NGX_TCP_NODELAY_DISABLED for fake stream connections.
Notably, it is to avoid setting the TCP_NODELAY flag for QUIC streams
in ngx_http_upstream_send_response().  It is an invalid operation on
inherently SOCK_DGRAM sockets, which leads to QUIC connection close.

The change reduces diff to the default branch in stream content phase.
2021-09-22 14:01:18 +03:00
Roman Arutyunyan
b2c8e690ce QUIC: simplified stream fd initialization. 2021-09-21 18:25:26 +03:00
Roman Arutyunyan
0f3eb180d2 HTTP/3: make ngx_http_log_error() static again.
This function was only referenced from ngx_http_v3_create_push_request() to
initialize push connection log.  Now the log handler is copied from the parent
request connection.

The change reduces diff to the default branch.
2021-09-17 16:32:23 +03:00
Roman Arutyunyan
00bb4e4b8d QUIC: separate event handling functions.
The functions ngx_quic_handle_read_event() and ngx_quic_handle_write_event()
are added.  Previously this code was a part of ngx_handle_read_event() and
ngx_handle_write_event().

The change simplifies ngx_handle_read_event() and ngx_handle_write_event()
by moving QUIC-related code to a QUIC source file.
2021-09-09 16:55:00 +03:00
Sergey Kandaurov
9d7f2e7917 HTTP/3: added CONNECT and TRACE methods rejection.
It has got lost in e1eb7f4ca9f1, let alone a subsequent update in 63c66b7cc07c.
2021-09-16 13:13:22 +03:00
Ruslan Ermilov
bd89c448b7 Removed NGX_OPENSSL_QUIC macro, NGX_QUIC is enough. 2021-09-14 12:09:13 +03:00
Sergey Kandaurov
10cafa75a4 HTTP/3: added debug logging of response fields.
Because of QPACK compression it's hard to see what fields are actually
sent by the server.
2021-09-13 16:25:37 +03:00
Sergey Kandaurov
bacd7ef0be HTTP/3: Huffman encoding for the Location response field. 2021-09-13 16:25:32 +03:00
Sergey Kandaurov
12cf623bc2 HTTP/3: Huffman encoding for the Last-Modified response field. 2021-09-13 16:25:31 +03:00
Sergey Kandaurov
ee5d927928 HTTP/3: Huffman encoding for the Content-Type response field. 2021-09-13 16:25:23 +03:00
Sergey Kandaurov
0ac1f6fd47 HTTP/3: implemented QPACK Huffman encoding for response fields. 2021-09-13 16:25:08 +03:00
Roman Arutyunyan
590996466c HTTP/3: reading body buffering in filters.
This change follows similar changes in HTTP/1 and HTTP/2 in 9cf043a5d9ca.
2021-09-09 15:47:29 +03:00
Sergey Kandaurov
4208e67e98 QUIC: removed Firefox workaround for trailing zeroes in datagrams.
This became unnecessary after discarding invalid packets since a6784cf32c13.
2021-09-09 19:12:27 +03:00
Ruslan Ermilov
ef94770e16 QUIC: macro style. 2021-09-09 15:40:08 +03:00
Sergey Kandaurov
f27686cf38 Merged with the default branch. 2021-09-08 15:53:00 +03:00
Roman Arutyunyan
465362e066 QUIC: store QUIC connection fd in stream fake connection.
Previously it had -1 as fd.  This fixes proxying, which relies on downstream
connection having a real fd.  Also, this reduces diff to the default branch for
ngx_close_connection().
2021-09-06 16:59:00 +03:00
Maxim Dounin
243469df65 HTTP/2: optimized processing of small DATA frames.
The request body filter chain is no longer called after processing
a DATA frame.  Instead, we now post a read event to do this.  This
ensures that multiple small DATA frames read during the same event loop
iteration are coalesced together, resulting in much faster processing.

Since rb->buf can now contain unprocessed data, window update is no
longer sent in ngx_http_v2_state_read_data() in case of flow control
being used due to filter buffering.  Instead, window will be updated
by ngx_http_v2_read_client_request_body_handler() in the posted read
event.
2021-09-06 14:54:50 +03:00
Maxim Dounin
584a30b4d5 HTTP/2: fixed timers left after request body reading.
Following rb->filter_need_buffering changes, request body reading is
only finished after the filter chain is called and rb->last_saved is set.
As such, with r->request_body_no_buffering, timer on fc->read is no
longer removed when the last part of the body is received, potentially
resulting in incorrect behaviour.

The fix is to call ngx_http_v2_process_request_body() from the
ngx_http_v2_read_unbuffered_request_body() function instead of
directly calling ngx_http_v2_filter_request_body(), so the timer
is properly removed.
2021-09-06 14:54:48 +03:00
Maxim Dounin
27fb6cdb9f HTTP/2: fixed window updates when buffering in filters.
In the body read handler, the window was incorrectly calculated
based on the full buffer size instead of the amount of free space
in the buffer.  If the request body is buffered by a filter, and
the buffer is not empty after the read event is generated by the
filter to resume request body processing, this could result in
"http2 negative window update" alerts.

Further, in the body ready handler and in ngx_http_v2_state_read_data()
the buffer wasn't cleared when the data were already written to disk,
so the client might stuck without window updates.
2021-09-06 14:54:47 +03:00
Mariano Di Martino
9985ab86bf QUIC: fixed null pointer dereference in MAX_DATA handler.
If a MAX_DATA frame was received before any stream was created, then the worker
process would crash in nginx_quic_handle_max_data_frame() while traversing the
stream tree.  The issue is solved by adding a check that makes sure the tree is
not empty.
2021-09-03 14:23:50 +03:00
Roman Arutyunyan
16557ff8b6 Fixed debug logging. 2021-09-02 12:25:37 +03:00
Roman Arutyunyan
3575f44a17 Version bump. 2021-09-03 17:19:33 +03:00
Sergey Kandaurov
72af057584 Merged with the default branch. 2021-09-01 10:57:25 +03:00
Maxim Dounin
15bf6d8cc9 HTTP/2: avoid memcpy() with NULL source and zero length.
Prodded by Clang Static Analyzer.
2021-08-31 16:44:13 +03:00
Sergey Kandaurov
1e8c0d4e06 Give GCC atomics precedence over deprecated Darwin atomic(3).
This allows to build nginx on macOS with -Wdeprecated-declarations.
2021-08-30 14:45:21 +03:00
Maxim Dounin
67d160bf25 Request body: reading body buffering in filters.
If a filter wants to buffer the request body during reading (for
example, to check an external scanner), it can now do so.  To make
it possible, the code now checks rb->last_saved (introduced in the
previous change) along with rb->rest == 0.

Since in HTTP/2 this requires flow control to avoid overflowing the
request body buffer, so filters which need buffering have to set
the rb->filter_need_buffering flag on the first filter call.  (Note
that each filter is expected to call the next filter, so all filters
will be able set the flag if needed.)
2021-08-29 22:22:02 +03:00
Maxim Dounin
2a70921380 Request body: introduced rb->last_saved flag.
It indicates that the last buffer was received by the save filter,
and can be used to check this at higher levels.  To be used in the
following changes.
2021-08-29 22:21:03 +03:00
Maxim Dounin
fd9d43b087 Request body: added alert to catch duplicate body saving.
If due to an error ngx_http_request_body_save_filter() is called
more than once with rb->rest == 0, this used to result in a segmentation
fault.  Added an alert to catch such errors, just in case.
2021-08-29 22:20:54 +03:00
Maxim Dounin
aa02695f5e Request body: missing comments about initialization. 2021-08-29 22:20:49 +03:00
Maxim Dounin
2862eb40e8 HTTP/2: improved handling of preread unbuffered requests.
Previously, fully preread unbuffered requests larger than client body
buffer size were saved to disk, despite the fact that "unbuffered" is
expected to imply no disk buffering.
2021-08-29 22:20:44 +03:00
Maxim Dounin
9f90d11cf5 HTTP/2: improved handling of END_STREAM in a separate DATA frame.
The save body filter saves the request body to disk once the buffer is full.
Yet in HTTP/2 this might happen even if there is no need to save anything
to disk, notably when content length is known and the END_STREAM flag is
sent in a separate empty DATA frame.  Workaround is to provide additional
byte in the buffer, so saving the request body won't be triggered.

This fixes unexpected request body disk buffering in HTTP/2 observed after
the previous change when content length is known and the END_STREAM flag
is sent in a separate empty DATA frame.
2021-08-29 22:20:38 +03:00
Maxim Dounin
78d9a3af91 HTTP/2: reworked body reading to better match HTTP/1.x code.
In particular, now the code always uses a buffer limited by
client_body_buffer_size.  At the cost of an additional copy it
ensures that small DATA frames are not directly mapped to small
write() syscalls, but rather buffered in memory before writing.
Further, requests without Content-Length are no longer forced
to use temporary files.
2021-08-29 22:20:36 +03:00
Maxim Dounin
301efb8a73 HTTP/2: improved body reading logging. 2021-08-29 22:20:34 +03:00
Maxim Dounin
c231640eba Upstream: fixed timeouts with gRPC, SSL and select (ticket #2229).
With SSL it is possible that an established connection is ready for
reading after the handshake.  Further, events might be already disabled
in case of level-triggered event methods.  If this happens and
ngx_http_upstream_send_request() blocks waiting for some data from
the upstream, such as flow control in case of gRPC, the connection
will time out due to no read events on the upstream connection.

Fix is to explicitly check the c->read->ready flag if sending request
blocks and post a read event if it is set.

Note that while it is possible to modify ngx_ssl_handshake() to keep
read events active, this won't completely resolve the issue, since
there can be data already received during the SSL handshake
(see 573bd30e46b4).
2021-08-20 03:53:56 +03:00
Alexey Radkov
3253b346fb Core: removed unnecessary restriction in hash initialization.
Hash initialization ignores elements with key.data set to NULL.
Nevertheless, the initial hash bucket size check didn't skip them,
resulting in unnecessary restrictions on, for example, variables with
long names and with the NGX_HTTP_VARIABLE_NOHASH flag.

Fix is to update the initial hash bucket size check to skip elements
with key.data set to NULL, similarly to how it is done in other parts
of the code.
2021-08-19 20:51:27 +03:00
Maxim Dounin
1fc61b7b1f SSL: SSL_sendfile() support with kernel TLS.
Requires OpenSSL 3.0 compiled with "enable-ktls" option.  Further, KTLS
needs to be enabled in kernel, and in OpenSSL, either via OpenSSL
configuration file or with "ssl_conf_command Options KTLS;" in nginx
configuration.

On FreeBSD, kernel TLS is available starting with FreeBSD 13.0, and
can be enabled with "sysctl kern.ipc.tls.enable=1" and "kldload ktls_ocf"
to load a software backend, see man ktls(4) for details.

On Linux, kernel TLS is available starting with kernel 4.13 (at least 5.2
is recommended), and needs kernel compiled with CONFIG_TLS=y (with
CONFIG_TLS=m, which is used at least on Ubuntu 21.04 by default,
the tls module needs to be loaded with "modprobe tls").
2021-10-21 18:44:07 +03:00
Maxim Dounin
3ab1b64463 Style: added missing "static" specifiers.
Mostly found by gcc -Wtraditional, per "non-static declaration of ...
follows static declaration [-Wtraditional]" warnings.
2021-10-21 18:43:13 +03:00
Maxim Dounin
f29d7ade54 Removed CLOCK_MONOTONIC_COARSE support.
While clock_gettime(CLOCK_MONOTONIC_COARSE) is faster than
clock_gettime(CLOCK_MONOTONIC), the latter is fast enough on Linux for
practical usage, and the difference is negligible compared to other costs
at each event loop iteration.  On the other hand, CLOCK_MONOTONIC_COARSE
causes various issues with typical CONFIG_HZ=250, notably very inaccurate
limit_rate handling in some edge cases (ticket #1678) and negative difference
between $request_time and $upstream_response_time (ticket #1965).
2021-10-21 18:38:38 +03:00
Vladimir Homutov
1fecec0cbf Mail: connections with wrong ALPN protocols are now rejected.
This is a recommended behavior by RFC 7301 and is useful
for mitigation of protocol confusion attacks [1].

For POP3 and IMAP protocols IANA-assigned ALPN IDs are used [2].
For the SMTP protocol "smtp" is used.

[1] https://alpaca-attack.com/
[2] https://www.iana.org/assignments/tls-extensiontype-values/
2021-10-20 09:45:34 +03:00
Vladimir Homutov
ebb6f7d656 HTTP: connections with wrong ALPN protocols are now rejected.
This is a recommended behavior by RFC 7301 and is useful
for mitigation of protocol confusion attacks [1].

To avoid possible negative effects, list of supported protocols
was extended to include all possible HTTP protocol ALPN IDs
registered by IANA [2], i.e. "http/1.0" and "http/0.9".

[1] https://alpaca-attack.com/
[2] https://www.iana.org/assignments/tls-extensiontype-values/
2021-10-20 09:50:02 +03:00
Vladimir Homutov
df472eecc0 Stream: the "ssl_alpn" directive.
The directive sets the server list of supported application protocols
and requires one of this protocols to be negotiated if client is using
ALPN.
2021-10-19 12:19:59 +03:00
Vladimir Homutov
a9f4f25b72 SSL: added $ssl_alpn_protocol variable.
The variable contains protocol selected by ALPN during handshake and
is empty otherwise.
2021-10-14 11:46:23 +03:00
Vladimir Homutov
1db517fb71 HTTP/2: removed support for NPN.
NPN was replaced with ALPN, published as RFC 7301 in July 2014.
It used to negotiate SPDY (and, in transition, HTTP/2).

NPN supported appeared in OpenSSL 1.0.1. It does not work with TLSv1.3 [1].
ALPN is supported since OpenSSL 1.0.2.

The NPN support was dropped in Firefox 53 [2] and Chrome 51 [3].

[1] https://github.com/openssl/openssl/issues/3665.
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1248198
[3] https://www.chromestatus.com/feature/5767920709795840
2021-10-15 10:02:15 +03:00
Maxim Dounin
dde319ee0c Upstream: fixed logging level of upstream invalid header errors.
In b87b7092cedb (nginx 1.21.1), logging level of "upstream sent invalid
header" errors was accidentally changed to "info".  This change restores
the "error" level, which is a proper logging level for upstream-side
errors.
2021-10-18 16:46:59 +03:00
Maxim Dounin
6119609cae Synced ngx_http_subrequest() argument names (ticket #2255). 2021-10-12 23:18:18 +03:00
Awdhesh Mathpal
2a88047ac1 Proxy: disabled keepalive on extra data in non-buffered mode.
The u->keepalive flag is initialized early if the response has no body
(or an empty body), and needs to be reset if there are any extra data,
similarly to how it is done in ngx_http_proxy_copy_filter().  Missed
in 83c4622053b0.
2021-10-07 19:23:11 -07:00
Maxim Dounin
c9c3f2f005 Fixed $content_length cacheability with chunked (ticket #2252). 2021-10-06 18:01:42 +03:00
Vladimir Homutov
e56ba23158 Stream: added half-close support.
The "proxy_half_close" directive enables handling of TCP half close.  If
enabled, connection to proxied server is kept open until both read ends get
EOF.  Write end shutdown is properly transmitted via proxy.
2021-09-22 10:20:00 +03:00
Roman Arutyunyan
adbd28b7a9 Request body: do not create temp file if there's nothing to write.
Do this only when the entire request body is empty and
r->request_body_in_file_only is set.

The issue manifested itself with missing warning "a client request body is
buffered to a temporary file" when the entire rb->buf is full and all buffers
are delayed by a filter.
2021-09-10 12:59:22 +03:00
Roman Arutyunyan
8165597cf6 Version bump. 2021-09-14 12:12:02 +03:00
Rob Mueller
d4dad02e5e Mail: Auth-SSL-Protocol and Auth-SSL-Cipher headers (ticket #2134).
This adds new Auth-SSL-Protocol and Auth-SSL-Cipher headers to
the mail proxy auth protocol when SSL is enabled.

This can be useful for detecting users using older clients that
negotiate old ciphers when you want to upgrade to newer
TLS versions of remove suppport for old and insecure ciphers.
You can use your auth backend to notify these users before the
upgrade that they either need to upgrade their client software
or contact your support team to work out an upgrade path.
2021-08-13 03:57:47 -04:00
Maxim Dounin
ce5996cdd1 SSL: ciphers now set before loading certificates (ticket #2035).
To load old/weak server or client certificates it might be needed to adjust
the security level, as introduced in OpenSSL 1.1.0.  This change ensures that
ciphers are set before loading the certificates, so security level changes
via the cipher string apply to certificate loading.
2021-08-16 22:40:31 +03:00
Sergey Kandaurov
926e0aa70a SSL: removed use of the SSL_OP_MSIE_SSLV2_RSA_PADDING option.
It has no effect since OpenSSL 0.9.7h and 0.9.8a.
2021-08-10 23:43:17 +03:00
Sergey Kandaurov
9e4e7a4e42 SSL: removed export ciphers support.
Export ciphers are forbidden to negotiate in TLS 1.1 and later protocol modes.
They are disabled since OpenSSL 1.0.2g by default unless explicitly configured
with "enable-weak-ssl-ciphers", and completely removed in OpenSSL 1.1.0.
2021-08-10 23:43:17 +03:00
Sergey Kandaurov
5155845ce4 SSL: use of the SSL_OP_IGNORE_UNEXPECTED_EOF option.
A new behaviour was introduced in OpenSSL 1.1.1e, when a peer does not send
close_notify before closing the connection.  Previously, it was to return
SSL_ERROR_SYSCALL with errno 0, known since at least OpenSSL 0.9.7, and is
handled gracefully in nginx.  Now it returns SSL_ERROR_SSL with a distinct
reason SSL_R_UNEXPECTED_EOF_WHILE_READING ("unexpected eof while reading").
This leads to critical errors seen in nginx within various routines such as
SSL_do_handshake(), SSL_read(), SSL_shutdown().  The behaviour was restored
in OpenSSL 1.1.1f, but presents in OpenSSL 3.0 by default.

Use of the SSL_OP_IGNORE_UNEXPECTED_EOF option added in OpenSSL 3.0 allows
to set a compatible behaviour to return SSL_ERROR_ZERO_RETURN:
https://git.openssl.org/?p=openssl.git;a=commitdiff;h=09b90e0

See for additional details: https://github.com/openssl/openssl/issues/11381
2021-08-10 23:43:17 +03:00
Sergey Kandaurov
3df7efd34b SSL: silenced warnings when building with OpenSSL 3.0.
The OPENSSL_SUPPRESS_DEPRECATED macro is used to suppress deprecation warnings.
This covers Session Tickets keys, SSL Engine, DH low level API for DHE ciphers.

Unlike OPENSSL_API_COMPAT, it works well with OpenSSL built with no-deprecated.
In particular, it doesn't unhide various macros in OpenSSL includes, which are
meant to be hidden under OPENSSL_NO_DEPRECATED.
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
9609288e7c SSL: ERR_peek_error_line_data() compatibility with OpenSSL 3.0.
ERR_peek_error_line_data() was deprecated in favour of ERR_peek_error_all().
Here we use the ERR_peek_error_data() helper to pass only used arguments.
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
b26858aa3c SSL: using SSL_CTX_set0_tmp_dh_pkey() with OpenSSL 3.0 in dhparam.
Using PEM_read_bio_DHparams() and SSL_CTX_set_tmp_dh() is deprecated
as part of deprecating the low level DH functions in favor of EVP_PKEY:
https://git.openssl.org/?p=openssl.git;a=commitdiff;h=163f6dc
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
ccc9bbad32 SSL: SSL_get_peer_certificate() is deprecated in OpenSSL 3.0.
Switch to SSL_get1_peer_certificate() when building with OpenSSL 3.0
and OPENSSL_NO_DEPRECATED defined.
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
36af236d6e SSL: RSA data type is deprecated in OpenSSL 3.0.
The only consumer is a callback function for SSL_CTX_set_tmp_rsa_callback()
deprecated in OpenSSL 1.1.0.  Now the function is conditionally compiled too.
2021-08-10 23:42:59 +03:00
Sergey Kandaurov
7bcb50c061 Disabled HTTP/1.0 requests with Transfer-Encoding.
The latest HTTP/1.1 draft describes Transfer-Encoding in HTTP/1.0 as having
potentially faulty message framing as that could have been forwarded without
handling of the chunked encoding, and forbids processing subsequest requests
over that connection: https://github.com/httpwg/http-core/issues/879.

While handling of such requests is permitted, the most secure approach seems
to reject them.
2021-08-09 18:12:12 +03:00
Sergey Kandaurov
02bd43d05b SSL: SSL_CTX_set_tmp_dh() error handling.
For example, it can fail due to weak DH parameters.
2021-08-04 21:27:51 +03:00
Maxim Dounin
15769c3918 SSL: set events ready flags after handshake.
The c->read->ready and c->write->ready flags might be reset during
the handshake, and not set again if the handshake was finished on
the other event.  At the same time, some data might be read from
the socket during the handshake, so missing c->read->ready flag might
result in a connection hang, for example, when waiting for an SMTP
greeting (which was already received during the handshake).

Found by Sergey Kandaurov.
2021-08-03 20:50:30 +03:00