Nyx by Example

Proxy TLS SNI

SNI lets OpenSSL choose the right certificate based on the hostname the client requested. tls_server_add_cert registers additional domains beyond the default cert. This enables one IP:443 to serve many HTTPS sites.

Code

// nyx-proxy TLS with SNI — multi-domain HTTPS on port 443
// TLS con SNI nyx-proxy — HTTPS multi-dominio en puerto 443

fn main() -> int {
    // SNI (Server Name Indication) lets one IP:443 serve multiple domains
    // with different TLS certificates. The client sends the hostname in
    // the TLS handshake, and the server picks the matching cert.

    // Primary certificate (default)
    let default_cert: String = "/etc/letsencrypt/live/nyxlang.com/fullchain.pem"
    let default_key: String = "/etc/letsencrypt/live/nyxlang.com/privkey.pem"

    // Initialize TLS server with default cert
    // tls_server_init(default_cert, default_key)

    // Add additional certs for other domains
    // tls_server_add_cert("/etc/letsencrypt/live/nyxkv.com/fullchain.pem",
    //                     "/etc/letsencrypt/live/nyxkv.com/privkey.pem")
    // tls_server_add_cert("/etc/letsencrypt/live/serve.nyxlang.com/fullchain.pem",
    //                     "/etc/letsencrypt/live/serve.nyxlang.com/privkey.pem")

    print("SNI config example:")
    print("  default: nyxlang.com")
    print("  +cert: nyxkv.com")
    print("  +cert: serve.nyxlang.com")
    print("  +cert: proxy.nyxlang.com")
    print("")
    print("OpenSSL selects the cert based on the client's SNI hint.")
    print("This is how nyx-proxy serves 4 domains on one port :443.")

    return 0
}

Output

SNI config example:
  default: nyxlang.com
  +cert: nyxkv.com
  +cert: serve.nyxlang.com
  +cert: proxy.nyxlang.com

OpenSSL selects the cert based on the client's SNI hint.
This is how nyx-proxy serves 4 domains on one port :443.

Explanation

Before SNI, each HTTPS site needed its own IP address because the certificate had to be chosen before the client could say which domain it wanted — a chicken-and-egg problem hard-coded into the TLS handshake. SNI (RFC 6066) fixed that by letting the client send the hostname in the first ClientHello packet, in the clear, so the server can pick the matching cert before encrypting anything else. tls_server_init sets the default cert and tls_server_add_cert adds more; under the hood OpenSSL maintains a hostname-to-SSL_CTX table and switches contexts on each handshake. This is the magic that lets nyx-proxy serve nyxlang.com, nyxkv.com, serve.nyxlang.com, and proxy.nyxlang.com all from one IPv4 on port 443.

← Previous Next →

Source: examples/by-example/89-proxy-tls-sni.nx