Traditional SSL/TLS implementations required separate IP addresses because the certificate exchange occurred before the HTTP Host header could be read. This created the widespread misconception that each certificate needed a dedicated IP. The technical limitation stemmed from the handshake sequence:
1. ClientHello → 2. ServerHello (with certificate) → 3. Key Exchange → 4. HTTP Request (with Host header)
Server Name Indication (SNI), defined in RFC 6066, extends TLS by including the requested hostname during the initial handshake:
ClientHello Extension: ExtensionType: server_name (0) ServerNameList: HostName: example.com
Modern web servers leverage this to select the appropriate certificate before establishing the secure connection.
Nginx Implementation
server { listen 443 ssl; server_name site1.example.com; ssl_certificate /path/to/site1.crt; ssl_certificate_key /path/to/site1.key; # Other directives... } server { listen 443 ssl; server_name site2.example.com; ssl_certificate /path/to/site2.crt; ssl_certificate_key /path/to/site2.key; # Other directives... }
Apache Configuration
<VirtualHost *:443> ServerName site1.example.com SSLEngine on SSLCertificateFile "/path/to/site1.crt" SSLCertificateKeyFile "/path/to/site1.key" # Other directives... </VirtualHost> <VirtualHost *:443> ServerName site2.example.com SSLEngine on SSLCertificateFile "/path/to/site2.crt" SSLCertificateKeyFile "/path/to/site2.key" # Other directives... </VirtualHost>
While SNI is supported by all modern browsers, some legacy clients may encounter issues:
- Internet Explorer on Windows XP
- Android Browser prior to 3.0
- Some embedded systems with custom TLS stacks
A fallback strategy might involve:
# Nginx default certificate for non-SNI clients ssl_certificate /path/to/default.crt; ssl_certificate_key /path/to/default.key;
Contrary to some expectations, SNI implementations typically have negligible performance overhead:
- TLS handshake remains largely unchanged
- Certificate selection adds minimal processing
- Memory usage scales linearly with certificate count
When implementing multi-certificate setups:
- Use separate private keys for each domain
- Regularly rotate certificates independently
- Monitor for certificate expiration across all domains
- Consider OCSP stapling configurations for each certificate
For years, the common wisdom stated that each SSL certificate required its own dedicated IP address. This was true during the SSLv3 and early TLS days due to the handshake process occurring before the server could see the requested hostname. The limitation stemmed from how the SSL/TLS protocol functioned:
Old SSL Handshake Flow:
1. Client connects to IP:443
2. SSL negotiation begins (before HTTP)
3. Server presents certificate
4. HTTP request reveals Host header (too late)
The game-changer was SNI (RFC 6066), which extends TLS to include the requested hostname during the initial handshake. Modern browsers (Chrome, Firefox, Edge) and servers (Apache 2.2.12+, Nginx 1.15.9+, IIS 8+) all support SNI.
Technical implementation requires:
- OpenSSL 0.9.8f or later
- Client-side SNI support (all modern browsers)
- Proper server configuration
<VirtualHost *:443>
ServerName domain1.com
SSLEngine on
SSLCertificateFile /path/to/domain1.crt
SSLCertificateKeyFile /path/to/domain1.key
# Other directives...
</VirtualHost>
<VirtualHost *:443>
ServerName domain2.com
SSLEngine on
SSLCertificateFile /path/to/domain2.crt
SSLCertificateKeyFile /path/to/domain2.key
# Other directives...
</VirtualHost>
server {
listen 443 ssl;
server_name domain1.com;
ssl_certificate /path/to/domain1.crt;
ssl_certificate_key /path/to/domain1.key;
# Other directives...
}
server {
listen 443 ssl;
server_name domain2.com;
ssl_certificate /path/to/domain2.crt;
ssl_certificate_key /path/to/domain2.key;
# Other directives...
}
While SNI solves the IP allocation problem, there are limitations:
- Legacy Clients: Windows XP with IE6/7 doesn't support SNI
- Non-browser Clients: Some API clients may have issues
- Certificate Validation: Some security scanners might flag SNI configurations
Use these OpenSSL commands to verify SNI is working:
# Test without SNI
openssl s_client -connect yourserver:443
# Test with SNI
openssl s_client -connect yourserver:443 -servername domain1.com
The output should show different certificates for each hostname when using the -servername
parameter.
Consider dedicated IP addresses if:
- You must support legacy clients (Windows XP users)
- Your application serves non-browser clients without SNI support
- You're using Extended Validation (EV) certificates (though this requirement is changing)