Commit Graph
297 Commits
Author SHA1 Message Date
Roman Arutyunyan a8289aa69c Script: avoid garbage at the end of the result string
If the script result turned out to be shorter than its predicted
length, the result string contained uninitialized bytes at the end.
The fix is to cut the result string by its actual size.

The following locations returned trailing garbage to the client with
URI "/1234abcd".

    map $uri $foo {
        ~^/(?<bar>[0-9]).*$ $bar;
    }

    location ~(?<bar>[0-9]*)[a-z]*$ {
        return 200 $1:$foo;
    }

    location ~(?<bar>[0-9]*)[a-z]*$ {
        set $qux $1:$foo;
        return 200 $qux;
    }
2026-07-15 19:51:22 +04:00
Maxim Dounin 4d32a2703c Access log: buffer overrun protection.
Similarly to generic script operations, access log script copy operations
now check if there is enough room in the buffer.

Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/ceff7ca7785a>
2026-07-15 19:51:22 +04:00
Maxim Dounin b767540492 Script: buffer overrun protection.
With this change, all script copy operations now check if there is
enough room in the buffer.  To do so, the script engine now provides the
e->end pointer, which specifies expected buffer end, and each copy
operation is checked against it with the ngx_http_script_check_length()
function.

The e->end pointer is optional and only checked when set, thus
introducing no incompatible API changes.  All standard functions were
updated to use it, notably ngx_http_complex_value(), ngx_http_script_run(),
ngx_http_script_regex_start_code(), ngx_http_script_complex_value_code().
Direct script evaluation in the proxy, fastcgi, scgi, uwsgi, grpc proxy,
index, and try_files modules will be updated by a separate patch.

In particular, this catches issues as observed when evaluating variables
with side effects, such as in the following configuration:

    map $uri $map {
        ~(?<capture>.*) $capture;
    }

    set $capture "";
    set $temp "$capture $map";

As well as when evaluating non-cacheable variables, where length of a
variable might change between length and copy codes, such as in the
following configuration:

    map prefix:$capture $map_volatile {
        volatile;
        ~(?<capture>.*) $capture;
    }

    set $capture "";
    set $temp "$map_volatile";

Similar changes were made in the stream module.

Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/d172f506ab5f>
2026-07-15 19:51:22 +04:00
Maxim Dounin 28219209e0 Script: simplified copy capture codes.
Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/0fd5e6155817>
2026-07-15 19:51:22 +04:00
Patrik Wall 6ab37e105c Stream: proxy_socket_sndbuf and proxy_socket_rcvbuf directives
Similarly to "listen ... sndbuf/rcvbuf", proxy_socket_sndbuf and
proxy_socket_rcvbuf can be used to set the SO_SNDBUF and SO_RCVBUF
socket options, respectively, on upstream connections.  By default,
the values are left unchanged.

Closes: https://github.com/nginx/nginx/issues/1297
2026-07-15 16:59:06 +04:00
Feng Wu 42f8df65b6 Add missing bounds check in ngx_{http,stream}_compile_complex_value()
Complex value compilation scans strings for $1..$9 capture references.
Check that a byte after '$' is present before testing it, matching
ngx_str_t length semantics and avoiding reliance on NUL termination.

Apply the same check to both HTTP and stream implementations.
2026-06-25 09:15:44 -07:00
Sergey Kandaurov 455fbf8c45 Style 2026-06-10 22:21:10 +04:00
Sergey Kandaurov d994f5b822 Split clients: improved calculation of range boundaries
If the last variant was given an explicit percentage to reach 100%, it
did not cover hash values on the range boundary or due to accumulating
rounding error.  Now this corresponds to the configuration with "*".
2026-06-09 19:04:17 +04:00
Vadim Zhestikov 1c387799ca SSL: add $ssl_sigalgs variable
The new $ssl_sigalgs variable lists all signature algorithms
advertised by the client in its ClientHello message,
colon-separated, in analogy to $ssl_ciphers and $ssl_curves.

On OpenSSL 4.0+, SSL_get0_sigalg() is used, which returns proper
TLS scheme names (e.g. "rsa_pkcs1_sha256", "ecdsa_secp256r1_sha256")
and falls back to "0xHHHH" hex for unknown schemes.

On OpenSSL 1.0.2+, SSL_get_sigalgs() is used.  Since OBJ_nid2sn()
on the combined psignhash NID is not injective across TLS
SignatureScheme codes (e.g. 0x0403 and 0x081a both yield
"ecdsa-with-SHA256"), raw SignatureScheme codes are reported to
avoid ambiguity and to match the hex fallback format of
SSL_get0_sigalg().

With older versions, as well as BoringSSL, LibreSSL, and AWS-LC,
the variable is empty.
2026-06-04 09:50:50 -07:00
Vladimir HomutovandRoman Arutyunyan 3b5da468b3 Stream: least_time balancer module
Example configuration:

upstream u {
    least_time connect | first_byte | last_byte [inflight];
    server a;
    server b;
}

Co-authored-by: Roman Arutyunyan <arut@nginx.com>
2026-05-04 21:19:40 +05:30
Vladimir Homutov 45554176ca Upstream: locked version of ngx_*_upstream_free_round_robin_peer().
This allows optimizing ngx_http_upstream_free_least_time_peer() by
not releasing and re-taking the same lock.
2026-05-04 21:19:40 +05:30
Sergey Kandaurov 484a9863e7 Stream: evaluate proxy_ssl_alpn once
To avoid disagreement with non-cacheable variables.
2026-04-30 15:07:34 +04:00
Vadim Zhestikov 98fc3bb78e Stream: support ALPN for proxy_ssl upstream.
Added the proxy_ssl_alpn directive, which sets the list of protocols
to advertise via ALPN during upstream TLS handshakes.  Each argument
is a complex value, so variables are accepted.  In particular,

    proxy_ssl_alpn $ssl_alpn_protocol;

inherits the protocol negotiated in the downstream TLS handshake.

When all evaluated values are empty or absent, no ALPN extension is
sent, equivalent to the directive not being set at all.

Closes #406 on GitHub.
2026-04-17 14:16:31 -07:00
Eugene Grebenschikov 0de6e878ba Fixed the "include" directive inside the "geo" block.
The "include" directive should be able to include multiple files if
given a filename mask.

Completes remaining changes introduced in da4ffd8.

Closes: https://github.com/nginx/nginx/issues/1165
2026-03-24 11:20:16 -07:00
Sergey Kandaurov 18711f7754 Stream: fixed client certificate validation with OCSP.
Check for OCSP status was missed in 581cf2267, resulting
in a broken validation.

Reported by Mufeed VH of Winfunc Research.
2026-03-24 19:28:20 +04:00
Sergey Kandaurov 920dc099c1 The "multipath" parameter of the "listen" directive.
When configured, it enables Multipath TCP support on a listen socket.
As of now it works on Linux starting with Linux 5.6 and glibc 2.32,
where it is enabled with an IPPROTO_MPTCP socket(2) protocol.

To avoid EADDRINUSE errors in bind() and listen() when transitioning
between sockets with different protocols, SO_REUSEPORT is set on both
sockets.  See f7f1607bf for potential implications.

Based on previous work by Maxime Dourov and Anthony Doeraene.
2026-03-19 01:13:51 +04:00
Aleksei Bavshin c5036ad30c Upstream: introduced a new macro for down value. 2026-03-09 11:08:30 -06:00
sftcd ab4f5b2d32 Add basic ECH shared-mode via OpenSSL. 2025-12-01 16:33:40 +04:00
Sergey Kandaurov 511abb19e1 Improved host header validation.
Validation is rewritten to follow RFC 3986 host syntax, based on
ngx_http_parse_request_line().  The following is now rejected:
- the rest of gen-delims "#", "?", "@", "[", "]"
- other unwise delims <">, "<", ">", "\", "^", "`', "{", "|", "}"
- IP literals with a trailing dot, missing closing bracket, or pct-encoded
- a port subcomponent with invalid values
- characters in upper half
2025-11-26 19:51:40 +04:00
Sergey Kandaurov 38a701d88b SSL: ngx_ssl_set_client_hello_callback() error handling.
The function interface is changed to follow a common approach
to other functions used to setup SSL_CTX, with an exception of
"ngx_conf_t *cf" since it is not bound to nginx configuration.

This is required to report and propagate SSL_CTX_set_ex_data()
errors, as reminded by Coverity (CID 1668589).
2025-11-10 20:01:28 +04:00
Roman Semenov ce30a1cb0d OCSP: fixed invalid type for the 'ssl_ocsp' directive. 2025-10-27 15:05:36 +04:00
Dmitry Plotnikov ac72ca60c7 Geo: the "volatile" parameter.
Similar to map's volatile parameter, creates a non-cacheable geo variable.
2025-10-24 15:06:54 -07:00
Sergey Kandaurov 71f8eb52b7 SSL: $ssl_sigalg, $ssl_client_sigalg.
Variables contain the IANA name of the signature scheme[1] used to sign
the TLS handshake.

Variables are only meaningful when using OpenSSL 3.5 and above, with older
versions they are empty.  Moreover, since this data isn't stored in a
serialized session, variables are only available for new sessions.

[1] https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml

Requested by willmafh.
2025-10-24 18:22:32 +04:00
Roman Arutyunyan 364a94ecec Upstream: reset local address in case of error.
After f10bc5a763 the address was set to NULL only when local address was
not specified at all.  In case complex value evaluated to an empty or
invalid string, local address remained unchanged.  Currenrly this is not
a problem since the value is only set once.  This change is a preparation
for being able to change the local address after initial setting.
2025-10-24 17:49:04 +04:00
Sergey Kandaurov 25b03d6500 SSL: disabled using certificate compression with OCSP stapling.
OCSP response in TLSv1.3 is sent in the Certificate message.  This
is incompatible with pre-compression of the configured certificates.
2025-10-08 19:56:41 +04:00
Sergey Kandaurov 7f9ced0ce0 SNI: support for early ClientHello callback with BoringSSL.
This brings feature parity with OpenSSL after the previous change,
making it possible to set SSL protocols per virtual server.
2025-09-25 19:25:08 +04:00
Sergey Kandaurov 0373fe5d98 SNI: using the ClientHello callback.
The change introduces an SNI based virtual server selection during
early ClientHello processing.  The callback is available since
OpenSSL 1.1.1; for older OpenSSL versions, the previous behaviour
is kept.

Using the ClientHello callback sets a reasonable processing order
for the "server_name" TLS extension.  Notably, session resumption
decision now happens after applying server configuration chosen by
SNI, useful with enabled verification of client certificates, which
brings consistency with BoringSSL behaviour.  The change supersedes
and reverts a fix made in 46b9f5d38 for TLSv1.3 resumed sessions.

In addition, since the callback is invoked prior to the protocol
version negotiation, this makes it possible to set "ssl_protocols"
on a per-virtual server basis.

To keep the $ssl_server_name variable working with TLSv1.2 resumed
sessions, as previously fixed in fd97b2a80, a limited server name
callback is preserved in order to acknowledge the extension.

Note that to allow third-party modules to properly chain the call to
ngx_ssl_client_hello_callback(), the servername callback function is
passed through exdata.
2025-09-25 19:25:08 +04:00
Sergey Kandaurov 251444fcf4 SSL: support for compressed server certificates with OpenSSL.
The ssl_certificate_compression directive allows to send compressed
server certificates.  In OpenSSL, they are pre-compressed on startup.
To simplify configuration, the SSL_OP_NO_TX_CERTIFICATE_COMPRESSION
option is automatically cleared if certificates were pre-compressed.

SSL_CTX_compress_certs() may return an error in legitimate cases,
e.g., when none of compression algorithms is available or if the
resulting compressed size is larger than the original one, thus it
is silently ignored.

Certificate compression is supported in Chrome with brotli only,
in Safari with zlib only, and in Firefox with all listed algorithms.
It is supported since Ubuntu 24.10, which has OpenSSL with enabled
zlib and zstd support.

The actual list of algorithms supported in OpenSSL depends on how
the library was configured; it can be brotli, zlib, zstd as listed
in RFC 8879.
2025-08-03 19:15:16 +04:00
Sergey Kandaurov 6c3a9d5612 Upstream: fixed passwords support for dynamic certificates.
Passwords were not preserved in optimized SSL contexts, the bug had
appeared in d791b4aab (1.23.1), as in the following configuration:

    server {
        proxy_ssl_password_file password;
        proxy_ssl_certificate $ssl_server_name.crt;
        proxy_ssl_certificate_key $ssl_server_name.key;

        location /original/ {
            proxy_pass https://u1/;
        }

        location /optimized/ {
            proxy_pass https://u2/;
        }
    }

The fix is to always preserve passwords, by copying to the configuration
pool, if dynamic certificates are used.  This is done as part of merging
"ssl_passwords" configuration.

To minimize the number of copies, a preserved version is then used for
inheritance.  A notable exception is inheritance of preserved empty
passwords to the context with statically configured certificates:

    server {
        proxy_ssl_certificate $ssl_server_name.crt;
        proxy_ssl_certificate_key $ssl_server_name.key;

        location / {
            proxy_pass ...;

            proxy_ssl_certificate example.com.crt;
            proxy_ssl_certificate_key example.com.key;
        }
    }

In this case, an unmodified version (NULL) of empty passwords is set,
to allow reading them from the password prompt on nginx startup.

As an additional optimization, a preserved instance of inherited
configured passwords is set to the previous level, to inherit it
to other contexts:

    server {
        proxy_ssl_password_file password;

        location /1/ {
            proxy_pass https://u1/;
            proxy_ssl_certificate $ssl_server_name.crt;
            proxy_ssl_certificate_key $ssl_server_name.key;
        }

        location /2/ {
            proxy_pass https://u2/;
            proxy_ssl_certificate $ssl_server_name.crt;
            proxy_ssl_certificate_key $ssl_server_name.key;
        }
    }
2025-04-10 17:27:45 +04:00
Sergey Kandaurov d16251969b SSL: removed stale comments.
It appears to be a relic from prototype locking removed in b0b7b5a35.
2025-02-26 17:40:03 +04:00
Sergey Kandaurov 311c390377 SSL: improved logging of saving sessions from upstream servers.
This makes it easier to understand why sessions may not be saved
in shared memory due to size.
2025-02-26 17:40:03 +04:00
Sergey Kandaurov 3d7304b527 SSL: using static storage for NGX_SSL_MAX_SESSION_SIZE buffers.
All such transient buffers are converted to the single storage in BSS.

In preparation to raise the limit.
2025-02-26 17:40:03 +04:00
Sergey Kandaurov 46b9f5d389 SNI: added restriction for TLSv1.3 cross-SNI session resumption.
In OpenSSL, session resumption always happens in the default SSL context,
prior to invoking the SNI callback.  Further, unlike in TLSv1.2 and older
protocols, SSL_get_servername() returns values received in the resumption
handshake, which may be different from the value in the initial handshake.
Notably, this makes the restriction added in b720f650b insufficient for
sessions resumed with different SNI server name.

Considering the example from b720f650b, previously, a client was able to
request example.org by presenting a certificate for example.org, then to
resume and request example.com.

The fix is to reject handshakes resumed with a different server name, if
verification of client certificates is enabled in a corresponding server
configuration.
2025-02-05 20:11:42 +04:00
Sergey KandaurovandAleksei Bavshin 454ad0ef33 Upstream: caching certificates and certificate keys with variables.
Caching is enabled with proxy_ssl_certificate_cache and friends.

Co-authored-by: Aleksei Bavshin <a.bavshin@nginx.com>
2025-01-17 04:37:46 +04:00
Sergey KandaurovandAleksei Bavshin 0e756d67aa SSL: caching certificates and certificate keys with variables.
A new directive "ssl_certificate_cache max=N [valid=time] [inactive=time]"
enables caching of SSL certificate chain and secret key objects specified
by "ssl_certificate" and "ssl_certificate_key" directives with variables.

Co-authored-by: Aleksei Bavshin <a.bavshin@nginx.com>
2025-01-17 04:37:46 +04:00
Sergey Kandaurov 476d6526b2 SSL: a new macro to set default protocol versions.
This simplifies merging protocol values after ea15896 and ebd18ec.

Further, as outlined in ebd18ec18, for libraries preceeding TLSv1.2+
support, only meaningful versions TLSv1 and TLSv1.1 are set by default.

While here, fixed indentation.
2024-11-22 13:47:22 +04:00
蕭澧邦 ea15896c1a SSL: fixed MSVC compilation after ebd18ec181.
MSVC generates a compilation error in case #if/#endif is used in a macro
parameter.
2024-11-11 22:29:55 +04:00
Mini Hawthorne 29aec5720f Upstream: copy upstream zone DNS valid time during config reload.
Previously, all upstream DNS entries would be immediately re-resolved
on config reload.  With a large number of upstreams, this creates
a spike of DNS resolution requests.  These spikes can overwhelm the
DNS server or cause drops on the network.

This patch retains the TTL of previous resolutions across reloads
by copying each upstream's name's expiry time across configuration
cycles.  As a result, no additional resolutions are needed.
2024-11-07 07:57:42 -08:00
Vladimir Homutov ea4654550a Upstream: per-upstream resolver.
The "resolver" and "resolver_timeout" directives can now be specified
directly in the "upstream" block.
2024-11-07 07:57:42 -08:00
Ruslan Ermilov 5ebe7a4122 Upstream: pre-resolve servers on reload.
After configuration is reloaded, it may take some time for the
re-resolvable upstream servers to resolve and become available
as peers.  During this time, client requests might get dropped.

Such servers are now pre-resolved using the "cache" of already
resolved peers from the old shared memory zone.
2024-11-07 07:57:42 -08:00
Dmitry Volyntsev 9fe119b431 Upstream: construct upstream peers from DNS SRV records. 2024-11-07 07:57:42 -08:00
db6870e06d Upstream: re-resolvable servers.
Specifying the upstream server by a hostname together with the
"resolve" parameter will make the hostname to be periodically
resolved, and upstream servers added/removed as necessary.

This requires a "resolver" at the "http" configuration block.

The "resolver_timeout" parameter also affects when the failed
DNS requests will be attempted again.  Responses with NXDOMAIN
will be attempted again in 10 seconds.

Upstream has a configuration generation number that is incremented each
time servers are added/removed to the primary/backup list.  This number
is remembered by the peer.init method, and if peer.get detects a change
in configuration, it returns NGX_BUSY.

Each server has a reference counter.  It is incremented by peer.get and
decremented by peer.free.  When a server is removed, it is removed from
the list of servers and is marked as "zombie".  The memory allocated by
a zombie peer is freed only when its reference count becomes zero.

Co-authored-by: Roman Arutyunyan <arut@nginx.com>
Co-authored-by: Sergey Kandaurov <pluknet@nginx.com>
Co-authored-by: Vladimir Homutov <vl@nginx.com>
2024-11-07 07:57:42 -08:00
Sergey Kandaurov ebd18ec181 SSL: disabled TLSv1 and TLSv1.1 by default.
TLSv1 and TLSv1.1 are formally deprecated and forbidden to negotiate due
to insufficient security reasons outlined in RFC 8996.

TLSv1 and TLSv1.1 are disabled in BoringSSL e95b0cad9 and LibreSSL 3.8.1
in the way they cannot be enabled in nginx configuration.  In OpenSSL 3.0,
they are only permitted at security level 0 (disabled by default).

The support is dropped in Chrome 84, Firefox 78, and deprecated in Safari.

This change disables TLSv1 and TLSv1.1 by default for OpenSSL 1.0.1 and
newer, where TLSv1.2 support is available.  For older library versions,
which do not have alternatives, these protocol versions remain enabled.
2024-10-31 19:49:00 +04:00
Sergey KandaurovandPraveen Chaudhary 18afcda938 SSL: optional ssl_client_certificate for ssl_verify_client.
Starting from TLSv1.1 (as seen since draft-ietf-tls-rfc2246-bis-00),
the "certificate_authorities" field grammar of the CertificateRequest
message was redone to allow no distinguished names.  In TLSv1.3, with
the restructured CertificateRequest message, this can be similarly
done by optionally including the "certificate_authorities" extension.
This allows to avoid sending DNs at all.

In practice, aside from published TLS specifications, all supported
SSL/TLS libraries allow to request client certificates with an empty
DN list for any protocol version.  For instance, when operating in
TLSv1, this results in sending the "certificate_authorities" list as
a zero-length vector, which corresponds to the TLSv1.1 specification.
Such behaviour goes back to SSLeay.

The change relaxes the requirement to specify at least one trusted CA
certificate in the ssl_client_certificate directive, which resulted in
sending DNs of these certificates (closes #142).  Instead, all trusted
CA certificates can be specified now using the ssl_trusted_certificate
directive if needed.  A notable difference that certificates specified
in ssl_trusted_certificate are always loaded remains (see 3648ba7db).

Co-authored-by: Praveen Chaudhary <praveenc@nvidia.com>
2024-09-20 14:43:00 +04:00
Sergey Kandaurov fb89d50eeb Stream: OCSP stapling. 2024-08-22 14:57:46 +04:00
Sergey Kandaurov 581cf22673 Stream: client certificate validation with OCSP. 2024-08-22 14:57:45 +04:00
Sergey Kandaurov 0fa8434957 Stream ssl_preread: do not reallocate a parsed SNI host.
We own this memory from the session pool.
2024-08-09 19:12:26 +04:00
Roman Arutyunyan 788e462c5b Stream: allow servers with no handler.
Previously handlers were mandatory.  However they are not always needed.
For example, a server configured with ssl_reject_handshake does not need a
handler.  Such servers required a fake handler to pass the check.  Now handler
absence check is moved to runtime.  If handler is missing, the connection is
closed with 500 code.
2024-06-27 17:29:56 +04:00
Roman Arutyunyan 489e1e6191 Stream pass: disabled passing from or to udp.
Passing from udp was not possible for the most part due to preread buffer
restriction.  Passing to udp could occasionally work, but the connection would
still be bound to the original listen rbtree, which prevented it from being
deleted on connection closure.
2024-05-03 20:26:05 +04:00
Roman Arutyunyan bf3e6538b9 Stream pass: limited the number of passes per connection.
Previously a cycle in pass configuration resulted in stack overflow.
2024-04-11 11:37:30 +04:00