How to Programmatically Detect SNI Usage in HTTPS Servers (Browser & CLI Methods)


2 views

html

Server Name Indication (SNI) is a critical TLS extension that enables hosting multiple SSL certificates on a single IP address. Detecting its usage helps in troubleshooting SSL configurations and assessing server capabilities. Here are practical methods to verify SNI implementation:

Modern browsers provide developer tools that reveal SNI information:

1. Open Chrome DevTools (F12)
2. Navigate to the Security tab
3. View certificate details
4. Check for "Subject Alternative Name" entries
5. Look for the message "This site is using Server Name Indication"

For Linux/Unix environments, OpenSSL provides direct SNI detection:

openssl s_client -connect example.com:443 -servername example.com 2>&1 | grep "server extension"

Expected output when SNI is supported:

TLS server extension "server name" (id=0), len=0

For automated testing, here's a Python script using PyOpenSSL:

import socket
from OpenSSL import SSL

def check_sni(hostname, port=443):
    context = SSL.Context(SSL.SSLv23_METHOD)
    conn = SSL.Connection(context, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
    conn.connect((hostname, port))
    conn.set_tlsext_host_name(hostname.encode())
    conn.do_handshake()
    return bool(conn.get_servername())

print(check_sni("example.com"))  # Returns True if SNI is supported

cURL with verbose output reveals SNI negotiation:

curl -v -I https://example.com --resolve example.com:443:127.0.0.1

Key indicators in output:

* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*  subject: CN=example.com
*  start date: ...
*  expire date: ...
*  subjectAltName: host "example.com" matched cert's "example.com"

For deep inspection, analyze the ClientHello message in TLS handshake:

  1. Filter for "tls.handshake.type == 1"
  2. Expand "Transport Layer Security" section
  3. Check for "Extension: server_name"
  • Load balancers may mask SNI behavior
  • Some servers accept SNI but don't require it
  • Old clients may fallback to non-SNI behavior

If methods return inconclusive results:

# Force non-SNI request for comparison
openssl s_client -connect example.com:443 -noservername

Compare certificate responses between SNI and non-SNI requests.


Server Name Indication (SNI) is a critical TLS extension that allows servers to host multiple SSL certificates on a single IP address. Here's how to detect its presence programmatically:

Using OpenSSL with SNI testing:

openssl s_client -connect example.com:443 -servername example.com 2>&1 | grep "server extension"

Alternative Python script with socket:

import socket
import ssl

hostname = 'example.com'
context = ssl.create_default_context()

try:
    with socket.create_connection((hostname, 443)) as sock:
        with context.wrap_socket(sock, server_hostname=hostname) as ssock:
            print(f"SNI supported: {'TLS_EXT_SERVER_NAME' in ssock.shared_ciphers()}")
except Exception as e:
    print(f"Error: {e}")

Modern browsers expose SNI information through Developer Tools:

  1. Open Chrome DevTools (F12)
  2. Navigate to Security tab
  3. View certificate details - SNI information appears in the extensions section

For comprehensive testing with different hostnames:

curl -v -k --resolve example.com:443:127.0.0.1 https://example.com 2>&1 | grep -i "TLS server name"

When testing SNI support:

  • Always test with multiple hostnames pointing to the same IP
  • Verify both IPv4 and IPv6 addresses if available
  • Check for legacy SSLv2/3 fallbacks which might not support SNI

For deep inspection using tcpdump:

tcpdump -i eth0 -s 0 -A 'tcp port 443 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x16030100)'

Look for the "server_name" extension in the Client Hello message.