We’re happy to announce the availability of NGINX Plus Release 28 (R28). Based on NGINX Open Source, NGINX Plus is the only all-in-one software web server, load balancer, reverse proxy, content cache, and API gateway.
New and enhanced features in NGINX Plus R28 include:
Additional TLS metrics – NGINX Plus R28 collects additional TLS statistics at the system‑wide, client‑side, and server‑side levels, providing insight that’s critical when troubleshooting SSL/TLS‑related errors in proxy configuration and for connections to clients and upstream servers.
The NGINX Plus live activity monitoring dashboard is updated to display the new SSL session data.
http
and stream
contexts which decode the TLV and define a variable for forwarding the client identifier to backend services.samesite
parameter – In NGINX Plus R28, the value of the samesite
parameter to the sticky
cookie
directive can be a variable. This improvement allows for easier management of traffic and more security.Rounding out the release are new features and bug fixes inherited from NGINX Open Source and updates to the NGINX JavaScript module.
Note: If you are upgrading from a release other than NGINX Plus R27, be sure to check the Important Changes in Behavior section in the announcement blogs for all releases between your current one and this one.
New operating systems and architectures supported:
Older operating systems removed:
Older operating systems and architectures deprecated and scheduled for removal in NGINX Plus R29:
Content-Length
and Transfer-Encoding
headers are now rejected as well as the responses with invalid Content-Length
or Transfer-Encoding
headers, or if both Content-Length
and Transfer-Encoding
are present in the responseObservability of SSL/TLS events and errors is important when troubleshooting TLS‑related problems with proxy configuration, upstream servers, and clients. Since the introduction of the NGINX Plus API in NGINX Plus R13, NGINX Plus has collected three TLS metrics at the system‑wide level:
handshakes
– Number of successful SSL handshakeshandshakes_failed
– Number of SSL handshake failures (which do not include certificate verification failures that happen after the SSL handshake)session_reuses
– Number of SSL session reusesIn NGINX Plus R27<.htmla> and later, you can configure collection of the three metrics for individual upstream servers and virtual servers.
NGINX Plus R28 expands the set of TLS metrics with new counters for handshake errors and certificate validation failures in both HTTP and Stream modules (here we provide examples only for HTTP modules, but the available Stream metrics are similar). For details on configuring metrics collection for individual upstream servers and virtual servers, see the NGINX Plus R27<.htmlspan> announcement blog.
Counters for the following handshake errors are new in NGINX Plus R28:
handshake_timeout
– Number of handshake failures due to handshake timeoutno_common_cipher
– Number of handshake failures due to lack of a common cipher between the parties in the handshake (not collected for connections to upstream servers because it does not apply)no_common_protocol
– Number of handshake failures due to lack of a common protocol between the partiespeer_rejected_cert
– Number of handshake failures due to the other party rejecting the certificate presented by NGINX Plus and providing the proper alert messageCertificate verification failures are now reported in the new verify_failures
section of API output when you configure certificate verification:
ssl_verify_client
[HTTP][Stream] directiveFor connections to servers with these protocol‑specific directives:
grpc_ssl_verify
proxy_ssl_verify
[HTTP][Stream]uwsgi_ssl_verify
When a certificate verification failure occurs, the metric for the corresponding cause is incremented and the connection torn down. Note, however, that the basic handshakes
counter is still incremented because these failures occur after the handshake succeeds.
The metrics for failed certificate validation are:
expired_cert
– Peer presented an expired certificatehostname_mismatch
– Server’s certificate doesn’t match the hostname (not collected for connections to clients)no_cert
– Client didn’t provide a certificate as required (not collected for connections to upstream servers)revoked_cert
– Peer presented a revoked certificateother
– Explicit counter for other certificate verification failuresHere’s a set of sample TLS metrics for HTTP connections at the system‑wide level:
$ curl 127.0.0.1:8080/api/8/ssl{
"handshakes": 32,
"session_reuses": 0,
"handshakes_failed": 8,
"no_common_protocol": 4,
"no_common_cipher": 2,
"handshake_timeout": 0,
"peer_rejected_cert": 0,
"verify_failures": {
"no_cert": 0,
"expired_cert": 2,
"revoked_cert": 1,
"hostname_mismatch": 2,
"other": 1
}
}
Here’s a set of sample metrics for connections between clients and the HTTP virtual server s9 (as noted previously, the hostname_mismatch
counter is not collected for such connections):
$ curl 127.0.0.1:8080/api/8/http/server_zones/s9{
...
"ssl": {
"handshakes": 0,
"session_reuses": 0,
"handshakes_failed": 1,
"no_common_protocol": 0,
"no_common_cipher": 1,
"handshake_timeout": 0,
"peer_rejected_cert": 0,
"verify_failures": {
"no_cert": 0,
"expired_cert": 0,
"revoked_cert": 0,
"other": 0
}
}
...
}
Here’s a set of sample metrics for HTTP connections to servers in the u2 upstream group (as noted previously, the no_cert
and no_common_cipher
counters are not collected for such connections):
$ curl 127.0.0.1:8080/api/8/http/upstreams/u2{
"peers": [
{
"id": 0,
"server": "127.0.0.1:8082",
"name": "127.0.0.1:8082",
...
"ssl": {
"handshakes": 1,
"session_reuses": 0,
"handshakes_failed": 0,
"no_common_protocol": 0,
"handshake_timeout": 0,
"peer_rejected_cert": 0,
"verify_failures": {
"expired_cert": 1,
"revoked_cert": 0,
"hostname_mismatch": 0,
"other": 0
}
},
...
}
],
}
For NGINX Plus R28 and later, the live activity monitoring dashboard displays the new TLS metrics described above. This screenshot shows metrics for connections to clients. To view the new metrics, mouse over the value in the SSL > Handshakes failed column as shown.
The three leading cloud providers – Amazon Web Services (AWS), Google Cloud Platform (GCP), and Microsoft Azure – each offer a “private service” where you can enable external clients to access your services without exposing them on the public Internet. Each service makes use of a client identifier which is represented in a type-length-value (TLV) vector in a PROXY protocol v2 header. The service‑specific identifiers are:
PP2_SUBTYPE_AWS_VPCE_ID
pscConnectionId
PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID
By default these client identifiers are not passed to backend services. NGINX Plus R28 introduces modules for the http
and stream
contexts – ngx_http_proxy_protocol_vendor_module and ngx_stream_proxy_protocol_vendor_module – which decode the TLV and define a variable for forwarding the identifier to backend services.
For general information about how NGINX Plus uses the PROXY protocol to obtain IP addresses and other information about clients, see Accepting the PROXY Protocol in the NGINX Plus Admin Guide.
In AWS, the source IP address for traffic coming from clients through a Virtual Private Cloud (VPC) endpoint service is the private IP address of the Network Load Balancer node. If the backend application requires the real IP addresses and other identifiers for clients, they can be obtained from PROXY protocol v2 headers.
In AWS, a custom TLV vector encodes the VPC ID of the endpoint in the PROXY protocol v2 header PP2_SUBTYPE_AWS_VPCE_ID
. (For more information, see the AWS documentation.)
Field | Length (Octets) | Description |
---|---|---|
Type | 1 | PP2_TYPE_AWS (0xEA ) |
Length | 2 | The length of value |
Value | 1 | PP2_SUBTYPE_AWS_VPCE_ID (0x01 ) |
Varies (value length minus 1) | The ID of the endpoint |
NGINX Plus R28 decodes the TLV and passes the endpoint ID to backend applications in the $proxy_protocol_tlv_aws_vpce_id
variable.
Note: In the server
block where you reference the $proxy_protocol_tlv_aws_vpce_id
variable, you must also include the proxy_protocol
parameter to the listen
[HTTP][Stream] directive. For an example, see line 8 of proxy_protocol_v2.conf just below.
This sample configuration for AWS checks that the VPC ID is acceptable and if so passes it to the backend application as the second parameter to the add_header
directive:
In GCP Private Service Connect, the source IP address for traffic coming from clients is an “address in one of the Private Service Connect subnets in the service producer’s VPC network”. If the backend application requires the real IP addresses and other identifiers for clients, they can be obtained from PROXY protocol v2 headers.
In GCP, a custom TLV vector encodes the unique (at the time) connection ID in the PROXY protocol v2 header pscConnectionId
. (For more information, see the GCP documentation.)
Field | Length (Bytes) | Description |
---|---|---|
Type | 1 | 0xE0 (PP2_TYPE_GCP ) |
Length | 2 | 0x8 (8 bytes) |
Value | 8 | The 8‑byte pscConnectionId in network order |
NGINX Plus R28 decodes the TLV and passes the value of pscConnectionId
to backend applications in the $proxy_protocol_tlv_gcp_conn_id
variable.
Note: In the server
block where you reference the $proxy_protocol_tlv_gcp_conn_id
variable, you must also include the proxy_protocol
parameter to the listen
[HTTP][Stream] directive. For an example, see line 8 of proxy_protocol_v2.conf above.
In Microsoft Azure Private Link, the source IP address for traffic coming from clients is the “network address translated (NAT) on the service provider side using the NAT IP [address] allocated from the provider’s virtual network”. If the backend application requires the real IP addresses and other identifiers for clients, they can be obtained from PROXY protocol v2 headers.
In Azure, a custom TLV vector encodes the client’s LinkID in the PROXY protocol v2 header PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID
. (For more information, see the Azure documentation.)
Field | Length (Octets) | Description |
---|---|---|
Type | 1 | PP2_TYPE_AZURE (0xEE ) |
Length | 2 | Length of value |
Value | 1 | PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID (0x01 ) |
4 | UINT32 (4 bytes) representing the LINKID of the private endpoint. Encoded in little‑endian format. |
NGINX Plus R28 decodes the TLV and passes the LinkID to backend applications in the $proxy_protocol_tlv_azure_pel_id
variable.
Note: In the server
block where you reference the $proxy_protocol_tlv_azure_pel_id
variable, you must also include the proxy_protocol
parameter to the listen
[HTTP][Stream] directive. For an example, see line 8 of proxy_protocol_v2.conf above.
samesite
ParameterIn previous NGINX Plus releases, three static values (strict
, lax
, and none
) were acceptable for the samesite
parameter to the sticky
cookie
directive. In NGINX Plus R28, the value can also be a variable.
By default (there is no samesite
parameter), NGINX does not inject the SameSite
attribute into the cookie. When the samesite
parameter is a variable, the result depends on how the variable resolves at runtime:
strict
, lax
, and none
) – NGINX injects the SameSite
attribute set to that value""
) – NGINX does not inject the SameSite
attributeSameSite
attribute set to Strict
(the most secure setting)This sample configuration sets the samesite
attribute based on the value of the HTTP User-Agent
header (this is good for legacy clients that don’t support the SameSite
attribute):
NGINX Plus R28 is based on NGINX Open Source 1.23.2. and inherits functional changes and bug fixes made since NGINX Plus R27 was released (in NGINX 1.23.0 through 1.23.2). Changes and bug fixes include:
ipv4=off
parameter to the HTTP resolver
directive disables lookup of IPv4 addresses.shared
parameter to the ssl_session_cache
directive, TLS session ticket keys are now rotated automatically.crit
to info
.For the full list of new features, changes, and bug fixes inherited from these releases, see the CHANGES file.
NGINX Plus R28 incorporates changes and fixes made in versions 0.7.5 through 0.7.8 of the NGINX JavaScript module (njs). We have highlighted some of the most significant ones in Make Your NGINX Config Even More Modular and Reusable with njs 0.7.7 on our blog. For a full list, see the Changes file.
If you’re running NGINX Plus, we strongly encourage you to upgrade to NGINX Plus R28 as soon as possible. You’ll also pick up several additional fixes and improvements, and it will help NGINX to help you when you need to raise a support ticket.
If you haven’t tried NGINX Plus, we encourage you to try it out – for security, load balancing, and API gateway, or as a fully supported web server with enhanced monitoring and management APIs. You can get started today with a free 30-day trial.
"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."