summaryrefslogtreecommitdiffhomepage
path: root/src (follow)
AgeCommit message (Collapse)AuthorFilesLines
2021-10-30Changed ngx_chain_update_chains() to test tag first (ticket #2248).Maxim Dounin1-4/+4
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-06Fixed $content_length cacheability with chunked (ticket #2252).Maxim Dounin1-0/+4
2021-08-20Upstream: fixed timeouts with gRPC, SSL and select (ticket #2229).Maxim Dounin1-0/+4
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-10SSL: use of the SSL_OP_IGNORE_UNEXPECTED_EOF option.Sergey Kandaurov1-0/+4
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-10SSL: silenced warnings when building with OpenSSL 3.0.Sergey Kandaurov1-0/+2
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-10SSL: ERR_peek_error_line_data() compatibility with OpenSSL 3.0.Sergey Kandaurov2-1/+6
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-10SSL: using SSL_CTX_set0_tmp_dh_pkey() with OpenSSL 3.0 in dhparam.Sergey Kandaurov1-1/+31
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-10SSL: SSL_get_peer_certificate() is deprecated in OpenSSL 3.0.Sergey Kandaurov1-0/+5
Switch to SSL_get1_peer_certificate() when building with OpenSSL 3.0 and OPENSSL_NO_DEPRECATED defined.
2021-08-10SSL: RSA data type is deprecated in OpenSSL 3.0.Sergey Kandaurov2-1/+7
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-04SSL: SSL_CTX_set_tmp_dh() error handling.Sergey Kandaurov1-1/+7
For example, it can fail due to weak DH parameters.
2021-08-03SSL: set events ready flags after handshake.Maxim Dounin1-0/+6
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-06-17gRPC: handling GOAWAY with a higher last stream identifier.Sergey Kandaurov1-0/+9
Previously, once received from upstream, it couldn't limit opening additional streams in a cached keepalive connection.
2021-06-01Fixed SSL logging with lingering close.Maxim Dounin3-0/+9
Recent fixes to SSL shutdown with lingering close (554c6ae25ffc, 1.19.5) broke logging of SSL variables. To make sure logging of SSL variables works properly, avoid freeing c->ssl when doing an SSL shutdown before lingering close. Reported by Reinis Rozitis (http://mailman.nginx.org/pipermail/nginx/2021-May/060670.html).
2021-06-01SSL: ngx_ssl_shutdown() rework.Maxim Dounin1-22/+21
Instead of calling SSL_free() with each return point, introduced a single place where cleanup happens. As a positive side effect, this fixes two potential memory leaks on ngx_handle_read_event() and ngx_handle_write_event() errors where there were no SSL_free() calls (though unlikely practical, as errors there are only expected to happen due to bugs or kernel issues).
2021-11-16Version bump.Maxim Dounin1-2/+2
2021-05-25Resolver: explicit check for compression pointers in question.Maxim Dounin1-0/+6
Since nginx always uses exactly one entry in the question section of a DNS query, and never uses compression pointers in this entry, parsing of a DNS response in ngx_resolver_process_response() does not expect compression pointers to appear in the question section of the DNS response. Indeed, compression pointers in the first name of a DNS response hardly make sense, do not seem to be allowed by RFC 1035 (which says "a pointer to a prior occurance of the same name", note "prior"), and were never observed in practice. Added an explicit check to ngx_resolver_process_response()'s parsing of the question section to properly report an error if compression pointers nevertheless appear in the question section.
2021-05-25Resolver: simplified ngx_resolver_copy().Maxim Dounin1-8/+5
Instead of checking on each label if we need to place a dot or not, now it always adds a dot after a label, and reduces the resulting length afterwards.
2021-05-25Resolver: reworked ngx_resolver_copy() copy loop.Maxim Dounin1-11/+7
To make the code easier to read, reworked the ngx_resolver_copy() copy loop to match the one used to calculate length. No functional changes.
2021-05-25Resolver: fixed label types handling in ngx_resolver_copy().Maxim Dounin1-0/+5
Previously, anything with any of the two high bits set were interpreted as compression pointers. This is incorrect, as RFC 1035 clearly states that "The 10 and 01 combinations are reserved for future use". Further, the 01 combination is actually allocated for EDNS extended label type (see RFC 2671 and RFC 6891), not really used though. Fix is to reject unrecognized label types rather than misinterpreting them as compression pointers.
2021-05-25Resolver: fixed off-by-one read in ngx_resolver_copy().Maxim Dounin1-0/+5
It is believed to be harmless, and in the worst case it uses some uninitialized memory as a part of the compression pointer length, eventually leading to the "name is out of DNS response" error.
2021-05-25Resolver: fixed off-by-one write in ngx_resolver_copy().Maxim Dounin1-4/+4
Reported by Luis Merino, Markus Vervier, Eric Sesterhenn, X41 D-Sec GmbH.
2021-05-25Version bump.Maxim Dounin1-2/+2
2021-04-20Stable branch.Maxim Dounin1-2/+2
2021-04-08Changed keepalive_requests default to 1000 (ticket #2155).Maxim Dounin2-2/+2
It turns out no browsers implement HTTP/2 GOAWAY handling properly, and large enough number of resources on a page results in failures to load some resources. In particular, Chrome seems to experience errors if loading of all resources requires more than 1 connection (while it is usually able to retry requests at least once, even with 2 connections there are occasional failures for some reason), Safari if loading requires more than 3 connections, and Firefox if loading requires more than 10 connections (can be configured with network.http.request.max-attempts, defaults to 10). It does not seem to be possible to resolve this on nginx side, even strict limiting of maximum concurrency does not help, and loading issues seems to be triggered by merely queueing of a request for a particular connection. The only available mitigation seems to use higher keepalive_requests value. The new default is 1000 and matches previously used default for http2_max_requests. It is expected to be enough for 99.98% of the pages (https://httparchive.org/reports/state-of-the-web?start=latest#reqTotal) even in Chrome.
2021-04-08Added $connection_time variable.Maxim Dounin1-0/+30
2021-04-08Introduced the "keepalive_time" directive.Maxim Dounin10-1/+46
Similar to lingering_time, it limits total connection lifetime before keepalive is switched off. The default is 1 hour, which is close to the total maximum connection lifetime possible with default keepalive_requests and keepalive_timeout.
2021-04-07HTTP/2: relaxed PRIORITY frames limit.Maxim Dounin1-1/+1
Firefox uses several idle streams for PRIORITY frames[1], and "http2_max_concurrent_streams 1;" results in "client sent too many PRIORITY frames" errors when a connection is established by Firefox. Fix is to relax the PRIORITY frames limit to use at least 100 as the initial value (which is the recommended by the HTTP/2 protocol minimum limit on the number of concurrent streams, so it is not unreasonable for clients to assume that similar number of idle streams can be used for prioritization). [1] https://hg.mozilla.org/mozilla-central/file/32a9e6e145d6e3071c3993a20bb603a2f388722b/netwerk/protocol/http/Http2Stream.cpp#l1270
2021-04-05Gzip: updated handling of zlib variant from Intel.Maxim Dounin1-26/+9
In current versions (all versions based on zlib 1.2.11, at least since 2018) it no longer uses 64K hash and does not force window bits to 13 if it is less than 13. That is, it needs just 16 bytes more memory than normal zlib, so these bytes are simply added to the normal size calculation.
2021-04-05Gzip: support for zlib-ng.Maxim Dounin1-2/+21
2021-04-05Version bump.Maxim Dounin1-2/+2
2021-03-28Fixed handling of already closed connections.Maxim Dounin3-7/+22
In limit_req, auth_delay, and upstream code to check for broken connections, tests for possible connection close by the client did not work if the connection was already closed when relevant event handler was set. This happened because there were no additional events in case of edge-triggered event methods, and read events were disabled in case of level-triggered ones. Fix is to explicitly post a read event if the c->read->ready flag is set.
2021-03-28Upstream: fixed broken connection check with eventport.Maxim Dounin1-0/+6
For connection close to be reported with eventport on Solaris, ngx_handle_read_event() needs to be called.
2021-03-28Upstream: fixed non-buffered proxying with eventport.Maxim Dounin1-3/+1
For new data to be reported with eventport on Solaris, ngx_handle_read_event() needs to be called after reading response headers. To do so, ngx_http_upstream_process_non_buffered_upstream() now called unconditionally if there are no prepread data. This won't cause any read() syscalls as long as upstream connection is not ready for reading (c->read->ready is not set), but will result in proper handling of all events.
2021-03-28Resolver: added missing event handling after reading.Maxim Dounin1-2/+17
If we need to be notified about further events, ngx_handle_read_event() needs to be called after a read event is processed. Without this, an event can be removed from the kernel and won't be reported again, notably when using oneshot event methods, such as eventport on Solaris. While here, error handling is also added, similar to one present in ngx_resolver_tcp_read(). This is not expected to make a difference and mostly added for consistency.
2021-03-28Events: fixed "port_dissociate() failed" alerts with eventport.Maxim Dounin1-1/+1
If an attempt is made to delete an event which was already reported, port_dissociate() returns an error. Fix is avoid doing anything if ev->active is not set. Possible alternative approach would be to avoid calling ngx_del_event() at all if ev->active is not set. This approach, however, will require something else to re-add the other event of the connection, since both read and write events are dissociated if an event is reported on a file descriptor. Currently ngx_eventport_del_event() re-associates write event if called to delete read event, and vice versa.
2021-03-26Events: fixed expiration of timers in the past.Maxim Dounin1-3/+1
If, at the start of an event loop iteration, there are any timers in the past (including timers expiring now), the ngx_process_events() function is called with zero timeout, and returns immediately even if there are no events. But the following code only calls ngx_event_expire_timers() if time actually changed, so this results in nginx spinning in the event loop till current time changes. While such timers are not expected to appear under normal conditions, as all such timers should be removed on previous event loop iterations, they still can appear due to bugs, zero timeouts set in the configuration (if this is not explicitly handled by the code), or due to external time changes on systems without clock_gettime(CLOCK_MONOTONIC). Fix is to call ngx_event_expire_timers() unconditionally. Calling it on each event loop iteration is not expected to be significant from performance point of view, especially compared to a syscall in ngx_process_events().
2021-03-26HTTP/2: improved handling of "keepalive_timeout 0".Maxim Dounin1-1/+3
Without explicit handling, a zero timer was actually added, leading to multiple unneeded syscalls. Further, sending GOAWAY frame early might be beneficial for clients. Reported by Sergey Kandaurov.
2021-03-24Cancel keepalive and lingering close on EOF better (ticket #2145).Sergey Kandaurov1-5/+5
Unlike in 75e908236701, which added the logic to ngx_http_finalize_request(), this change moves it to a more generic routine ngx_http_finalize_connection() to cover cases when a request is finalized with NGX_DONE. In particular, this fixes unwanted connection transition into the keepalive state after receiving EOF while discarding request body. With edge-triggered event methods that means the connection will last for extra seconds as set in the keepalive_timeout directive.
2021-03-23gRPC: fixed handling of padding on DATA frames.Maxim Dounin1-11/+24
The response size check introduced in 39501ce97e29 did not take into account possible padding on DATA frames, resulting in incorrect "upstream sent response body larger than indicated content length" errors if upstream server used padding in responses with known length. Fix is to check the actual size of response buffers produced by the code, similarly to how it is done in other protocols, instead of checking the size of DATA frames. Reported at: http://mailman.nginx.org/pipermail/nginx-devel/2021-March/013907.html
2021-03-11Removed "ch" argument from ngx_pass_open_channel().Ruslan Ermilov1-39/+18
2021-03-11Mail: fixed build without SSL.Maxim Dounin2-5/+7
Broken by d84f13618277 and 12ea1de7d87c (1.19.8). Reported by Sergey Osokin.
2021-03-11Version bump.Maxim Dounin1-2/+2
2021-03-05Mail: sending of the PROXY protocol to backends.Maxim Dounin2-7/+133
Activated with the "proxy_protocol" directive. Can be combined with "listen ... proxy_protocol;" and "set_real_ip_from ...;" to pass client address provided to nginx in the PROXY protocol header.
2021-03-05Mail: realip module.Maxim Dounin3-0/+275
When configured with the "set_real_ip_from", it can set client's IP address as visible in logs to the one obtained via the PROXY protocol.
2021-03-05Mail: parsing of the PROXY protocol from clients.Maxim Dounin5-4/+132
Activated with the "proxy_protocol" parameter of the "listen" directive. Obtained information is passed to the auth_http script in Proxy-Protocol-Addr, Proxy-Protocol-Port, Proxy-Protocol-Server-Addr, and Proxy-Protocol-Server-Port headers.
2021-03-05Mail: made auth http creating request easier to extend.Maxim Dounin1-13/+29
2021-03-05Mail: fixed log action after SSL handshake.Maxim Dounin1-0/+2
2021-03-05Mail: postponed session initialization under accept mutex.Maxim Dounin2-1/+29
Similarly to 40e8ce405859 in the stream module, this reduces the time accept mutex is held. This also simplifies following changes to introduce PROXY protocol support.
2021-03-05Mail: added missing event handling after reading data.Maxim Dounin5-8/+75
If we need to be notified about further events, ngx_handle_read_event() needs to be called after a read event is processed. Without this, an event can be removed from the kernel and won't be reported again, notably when using oneshot event methods, such as eventport on Solaris. For consistency, existing ngx_handle_read_event() call removed from ngx_mail_read_command(), as this call only covers one of the code paths where ngx_mail_read_command() returns NGX_AGAIN. Instead, appropriate processing added to the callers, covering all code paths where NGX_AGAIN is returned.
2021-03-05Mail: added missing event handling after blocking events.Maxim Dounin3-0/+18
As long as a read event is blocked (ignored), ngx_handle_read_event() needs to be called to make sure no further notifications will be triggered when using level-triggered event methods, such as select() or poll().