When configuring SSL certificates in IIS, it's frustrating to see the wrong certificate being served despite proper configuration. Let's dive deep into potential causes and solutions.
First, confirm your certificate bindings using PowerShell:
# List all SSL bindings
Get-ChildItem IIS:\SslBindings
# Alternative method using netsh
netsh http show sslcert
Several factors could cause this behavior:
- Hostname mismatch in certificate SAN
- Incorrect SNI configuration
- Port sharing conflicts
- Certificate store permissions
- DNS resolution issues
Use OpenSSL to verify what certificate is actually being served:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com | openssl x509 -text -noout
Try explicitly binding the certificate using PowerShell:
# Remove existing binding
Remove-WebBinding -Name "Default Web Site" -Protocol "https" -Port 443
# Add new binding with specific cert thumbprint
New-WebBinding -Name "Default Web Site" -Protocol "https" -Port 443 -SslFlags 1
$cert = Get-Item cert:\LocalMachine\My\THUMBPRINT_HERE
New-Item IIS:\SslBindings\0.0.0.0!443 -Value $cert
For modern browsers, ensure SNI is properly configured:
# Enable SNI for a specific binding
Set-WebBinding -Name "Default Web Site" -PropertyName "SslFlags" -Value 1
Remember to check IIS logs for detailed error information:
Get-Content C:\inetpub\logs\LogFiles\W3SVC1\u_ex[date].log -Tail 100
After making changes, verify with this comprehensive test:
Test-NetConnection -ComputerName localhost -Port 443
Get-ChildItem cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq "YOUR_THUMBPRINT"}
html
When IIS serves an unexpected SSL certificate despite proper configuration, it typically indicates one of these underlying issues:
- SNI (Server Name Indication) conflicts in multi-site hosting
- Incorrect certificate binding at the IP/port level
- Certificate store selection errors
- Configuration caching issues
First, let's validate certificate bindings using PowerShell:
# List all SSL bindings
Get-ChildItem IIS:\SslBindings
# Check specific IP binding
Get-WebBinding -Name "YourSiteName" -Protocol "https" | Select-Object *
For IP-based bindings (especially important when using dedicated IPs):
netsh http show sslcert ipport=0.0.0.0:443
If you're hosting multiple sites on the same IP, SNI becomes crucial. Verify SNI settings with:
Import-Module WebAdministration
Get-ChildItem IIS:\Sites | ForEach-Object {
$site = $_
$bindings = Get-WebBinding -Name $site.Name
$bindings | Where-Object { $_.Protocol -eq "https" } | ForEach-Object {
[PSCustomObject]@{
SiteName = $site.Name
Binding = $_.BindingInformation
CertificateHash = $_.CertificateHash
CertificateStoreName = $_.CertificateStoreName
SniFlags = $_.SniFlags
}
}
}
Sometimes the certificate exists in multiple stores causing conflicts. Check all stores:
# Check all certificate stores
Get-ChildItem Cert:\LocalMachine -Recurse | Where-Object { $_.Thumbprint -eq "DC0D3FF5D752CD58FD291C48F30646FD9E0D8AED" }
# Compare with IIS binding
(Get-WebBinding -Name "YourSiteName" -Protocol "https").CertificateHash
Old bindings sometimes persist. Try removing and recreating:
# Remove existing binding
Remove-WebBinding -Name "YourSiteName" -Protocol "https" -HostHeader "yourdomain.com"
# Add fresh binding
New-WebBinding -Name "YourSiteName" -Protocol "https" -Port 443 -IPAddress "*" -HostHeader "yourdomain.com"
$cert = Get-Item Cert:\LocalMachine\My\DC0D3FF5D752CD58FD291C48F30646FD9E0D8AED
$cert | New-WebBinding -Name "YourSiteName" -Protocol "https" -Port 443 -SslFlags 1
Inspect IIS configuration file directly:
# Path to config file
$configPath = "$env:SystemRoot\System32\inetsrv\config\applicationHost.config"
# View SSL settings
Select-String -Path $configPath -Pattern "binding protocol=""https"""
When everything fails, reset all bindings:
# Backup current configuration
appcmd list config /section:system.applicationHost/sites /config /xml > iis_backup.xml
# Clear all SSL bindings
netsh http delete sslcert ipport=0.0.0.0:443
Get-WebBinding | Where-Object { $_.Protocol -eq "https" } | Remove-WebBinding
# Recreate bindings
$cert = Get-Item Cert:\LocalMachine\My\DC0D3FF5D752CD58FD291C48F30646FD9E0D8AED
New-WebBinding -Name "YourSiteName" -Protocol "https" -Port 443
$cert | New-ItemProperty -Path "IIS:\SslBindings\0.0.0.0!443" -Name "CertificateHash" -Value $cert.GetCertHash()
- Verify certificate is in "Personal" store (LocalMachine\My)
- Ensure private key permissions are correct (use winhttpcertcfg if needed)
- Check for conflicting bindings in other sites
- Restart IIS and the server if necessary
- Test with OpenSSL:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com