Server Name Indication (SNI) sends the requested hostname in the TLS handshake, letting one IP address serve different certificates and sites. Without SNI, separate addresses were one solution, but a shared certificate covering several subject alternative names (SANs) or an appropriate wildcard could also serve multiple sites. The problem is ordering: in a full certificate-based HTTPS handshake without early data, certificate selection precedes the encrypted HTTP request that identifies the application.

This article focuses on nginx configuration: which server block supplies the certificate, what unmatched names encounter, and what an inspection command actually proves. Certificate selection, client verification, and application routing are separate decisions.

The name goes first

The client includes SNI in ClientHello. nginx can use that name while choosing the TLS server configuration; the extension does not require a separate request round trip. Avoid describing everything as happening before encryption: TLS 1.3 encrypts the certificate message after ServerHello.

The client must send SNI for name-based selection at this stage. Without it, nginx starts from the default server for the listening address and port. That server may offer a certificate or reject the handshake. If a certificate is offered, the client still needs to validate its chain and expected identity; receiving a certificate is not acceptance.

Match by server_name block

nginx compares the SNI name against server_name entries for the relevant listener. Matching prioritizes exact names, then the longest leading wildcard, the longest trailing wildcard, and the first matching regular expression. Certificate settings may be inherited or shared; every name does not require its own certificate.

Keep a record linking each intended name, certificate SAN, server_name rule, and application route. nginx wildcard matching and certificate wildcard matching have different scopes: a configuration match alone does not establish certificate coverage.

A correct certificate does not guarantee the correct application. nginx can select a server configuration again while processing the HTTP request line and Host header. SNI for one site and Host for another do not replace the handshake’s certificate, and TLS does not certify the response’s business meaning. Define the intended cross-name routing policy and check both layers.

Control the default fallback

For each listening address and port, use default_server to make the intended default explicit. Without that designation, the first server for that listener is the default. Missing or unmatched SNI therefore needs a deliberate policy, rather than an assumption that the first certificate always wins.

The default may serve a suitable certificate or reject the TLS handshake with ssl_reject_handshake, available since nginx 1.19.4. An HTTP landing page or return 444 acts later, after TLS; it cannot repair a certificate mismatch that prevents the client from sending HTTP. Test unknown-name and no-SNI cases separately against the chosen policy.

When it breaks

If a new hostname receives an unexpected certificate, inspect the listener, included configuration, server_name spelling, and certificate assignment. A successful nginx -T checks and prints configuration files; it does not prove the running workers loaded that version. The filtered excerpt below can omit relevant settings and errors. Compare the full output and reload result before blaming name matching.

Without Encrypted Client Hello (ECH), ordinary ClientHello SNI is visible to network observers. TLS 1.3 alone does not hide it. Successfully negotiated ECH protects the inner ClientHello, including its target name, but does not conceal every traffic characteristic. No ECH deployment or privacy measurement is established here.

In a full certificate-based HTTPS handshake without early data, SNI in ClientHello selects TLS configuration and its certificate. The later encrypted HTTP Host participates in request routing, so a correct certificate does not prove the right application was selected.
The TLS name arrives before HTTP. Static mechanism illustration; no TLS connection or article command was run.

Check it quickly

This is an unexecuted diagnostic template, not a verified deployment. Replace the documentation address and example names with targets in your own authorized environment before use:

nginx -T 2>&1 | grep -B2 -A4 'server_name\|ssl_certificate ' | head -n 40
openssl s_client -connect 203.0.113.10:443 -servername shop.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer
openssl s_client -connect 203.0.113.10:443 -servername unknown.invalid </dev/null 2>/dev/null | openssl x509 -noout -subject

The pipelines print certificate subject/issuer fields. They neither display SAN coverage nor establish hostname and chain validation. Diagnostics are suppressed, and s_client normally continues after verification errors unless configured otherwise; empty output alone does not prove intentional rejection.

Separately check SAN identity, trust chain, validity dates, and verification failures using the installed OpenSSL version’s documented verification controls. Confirm known-name selection, unknown-name and no-SNI policy, and application routing in that authorized environment. Shared certificates are valid when they cover the intended identities; an unmatched name may receive the configured default or be rejected. These outcomes remain untested here.

Sources

Official documentation accessed 2026-10-18 for the claims above; this is source review, not runtime verification.