Optimizing SSL Hosting Without SNI for Wildcard Certificates in IIS: A Technical Deep Dive


9 views

When hosting multiple HTTPS sites on a single IP address with a wildcard certificate (*.example.com), the SSL handshake process becomes simpler than scenarios requiring SNI. Here's why:

// Example IIS binding configuration (web.config snippet)
<bindings>
    <binding protocol="https" bindingInformation="*:443:example.com" certificateHash="WILDCARD_CERT_THUMBPRINT" />
    <binding protocol="https" bindingInformation="*:443:sub1.example.com" certificateHash="WILDCARD_CERT_THUMBPRINT" />
    <binding protocol="https" bindingInformation="*:443:sub2.example.com" certificateHash="WILDCARD_CERT_THUMBPRINT" />
</bindings>

Without SNI enabled, IIS follows these certificate selection rules:

  • First-match principle: IIS serves the certificate from the first binding that matches the requested hostname
  • Fallback behavior: If no direct match found, IIS uses the first binding's certificate that covers the domain (wildcard match)
  • No hostname verification: The actual certificate selection occurs before hostname validation in the TLS handshake

When adding example.org with a different certificate:

// PowerShell to enable SNI for specific binding
New-WebBinding -Name "ExampleOrgSite" -Protocol "https" -Port 443 -IPAddress "*" -HostHeader "example.org" -SslFlags 1

Key observations:

  • SNI-enabled bindings won't affect non-SNI sites when using different certificates
  • IIS maintains separate binding lists for SNI and non-SNI configurations
  • Certificate selection becomes hostname-aware for SNI-enabled sites only

Testing matrix for various client scenarios:

Client SNI Support Wildcard Compatibility
Windows XP (IE6) No Works
Android 2.3 No Works
Modern Browsers Yes Works

For mixed environments where some sites need SNI:

// Using Application Request Routing for certificate selection
<system.webServer>
    <rewrite>
        <rules>
            <rule name="SNI-Redirect" patternSyntax="Wildcard">
                <match url="*" />
                <conditions>
                    <add input="{HTTP_HOST}" pattern="example.org" />
                </conditions>
                <action type="Rewrite" url="https://example.org/{R:0}" />
            </rule>
        </rules>
    </rewrite>
</system.webServer>

When hosting multiple HTTPS sites on a single IIS server with the same IP address, the standard approach requires Server Name Indication (SNI) to distinguish between sites. However, when all sites share a wildcard certificate (e.g., *.example.com), SNI becomes optional. Here's why:

  • The same certificate validates for all subdomains (example.com, sub1.example.com, sub2.example.com)
  • IIS can serve the wildcard cert regardless of which specific subdomain is requested
  • Non-SNI clients (like Windows XP) can still establish secure connections

Without SNI enabled, IIS follows this certificate selection logic:

// Pseudocode representing IIS's internal logic
if (SSL_request_received) {
    if (SNI_enabled) {
        return certificate_matching_SNI_hostname;
    } else {
        return first_registered_certificate_for_port_443;
    }
}

In practice, IIS will use whichever certificate is bound to the first site in the binding order for that IP:port combination. This makes the binding order critically important in non-SNI configurations.

When introducing a new domain with a different certificate (example.org), you can selectively enable SNI:

// PowerShell to enable SNI for specific site
Import-Module WebAdministration
Set-WebBinding -Name "Example.org Site" -Protocol "https" -PropertyName "SslFlags" -Value 1

This configuration allows:

  • example.org to use SNI with its dedicated certificate
  • All *.example.com sites to continue using the wildcard cert without SNI

While this setup generally works, consider testing these scenarios:

  1. Clients with outdated SSL/TLS implementations
  2. Mobile devices with peculiar certificate validation behaviors
  3. Applications making API calls with strict certificate pinning

To ensure long-term stability:

# Batch script to verify bindings
@echo off
for /f "tokens=2 delims=:" %%a in ('netsh http show sslcert ^| findstr /C:"IP:port"') do (
    echo Checking cert for %%a
    openssl s_client -connect %%a -servername example.com | openssl x509 -noout -subject
)

Remember to document your certificate bindings and periodically verify that automation tools haven't altered your carefully configured setup.