Detailed explanation of SSL certificate installation and configuration differences between different IIS versions to help you correctly configure SSL certificates
| IIS Version | Windows Server | SNI Support | TLS 1.2 | TLS 1.3 | PowerShell Support |
|---|---|---|---|---|---|
| IIS 6.0 | 2003 | ❌ | ⚠️ Needs Configuration | ❌ | ❌ |
| IIS 7.0 | 2008 | ❌ | ✅ | ❌ | ✅ |
| IIS 7.5 | 2008 R2 | ❌ | ✅ | ❌ | ✅ |
| IIS 8.0 | 2012 | ✅ | ✅ | ❌ | ✅ |
| IIS 8.5 | 2012 R2 | ✅ | ✅ | ❌ | ✅ |
| IIS 10.0 | 2016/2019/2022 | ✅ | ✅ | ✅ | ✅ |
IIS requires certificate files in .pfx or .p12 format. If you receive .crt and .key files, you need to convert them to .pfx format first.
# # Merge certificate chain (if needed)cat your_domain.crt intermediate_ca.crt > fullchain.crt
# # Convert to PFX formatopenssl pkcs12 -export -out your_domain.pfx -inkey your_domain.key -in fullchain.crt
# # System will prompt you to set PFX password, please keep this password safe
All IIS versions support importing certificates through graphical interface, but the interface is slightly different:
Open "Server Manager" → "Tools" → "Internet Information Services (IIS) Manager"
# # Import PFX certificate to local computer personal store$pfxPath = "C:\path\to\your_domain.pfx"
$password = ConvertTo-SecureString -String "YourPFXPassword" -Force -AsPlainText
Import-PfxCertificate -FilePath $pfxPath -CertStoreLocation Cert:\LocalMachine\My -Password $password
# # Verify certificate import successGet-ChildItem -Path Cert:\LocalMachine\My | Where-Object {`$_.Subject -like "*yourdomain.com*"}
# # Import WebAdministration moduleImport-Module WebAdministration
# # Import certificate$pfxPath = "C:\path\to\your_domain.pfx"
$password = "YourPFXPassword"
$cert = Import-PfxCertificate -FilePath $pfxPath -CertStoreLocation Cert:\LocalMachine\My -Password (ConvertTo-SecureString -String $password -Force -AsPlainText)
# # Verify importGet-ChildItem IIS:\SslBindings
# # Import WebAdministration moduleImport-Module WebAdministration
# # Get certificate thumbprint$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {`$_.Subject -like "*yourdomain.com*"}
$thumbprint = $cert.Thumbprint
# # Bind certificate to site (without SNI)New-WebBinding -Name "YourSiteName" -Protocol https -Port 443 -SslFlags 0
# # Assign certificate to binding$binding = Get-WebBinding -Name "YourSiteName" -Protocol https
$binding.AddSslCertificate($thumbprint, "My")
# # IIS 8.0+ use SNI bindingNew-WebBinding -Name "YourSiteName" -Protocol https -Port 443 -HostHeader "yourdomain.com" -SslFlags 1
$binding = Get-WebBinding -Name "YourSiteName" -Protocol https -HostHeader "yourdomain.com"
$binding.AddSslCertificate($thumbprint, "My")
SslFlags 0:SslFlags 0: Do not use SNI (IIS 7.0/7.5)SslFlags 1:SslFlags 1: Use SNI (IIS 8.0+)SNI allows binding multiple SSL certificates on the same IP address, each certificate corresponding to a different domain name. This is very useful for shared hosting environments.
# # Configure SNI for multiple domainsImport-Module WebAdministration
# # Site 1: yourdomain.com$cert1 = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {`$_.Subject -like "*yourdomain.com*"}
New-WebBinding -Name "Site1" -Protocol https -Port 443 -HostHeader "yourdomain.com" -SslFlags 1
$binding1 = Get-WebBinding -Name "Site1" -Protocol https -HostHeader "yourdomain.com"
$binding1.AddSslCertificate($cert1.Thumbprint, "My")
# # Site 2: anotherdomain.com (same IP)$cert2 = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {`$_.Subject -like "*anotherdomain.com*"}
New-WebBinding -Name "Site2" -Protocol https -Port 443 -HostHeader "anotherdomain.com" -SslFlags 1
$binding2 = Get-WebBinding -Name "Site2" -Protocol https -HostHeader "anotherdomain.com"
$binding2.AddSslCertificate($cert2.Thumbprint, "My")
Windows Server TLS protocol configuration is done through registry, different versions support different protocols:
# # View enabled TLS protocolsGet-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" -Name Enabled
# # View all TLS protocol statusGet-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols" | ForEach-Object {
$protocol = `$_.PSChildName
$path = `$_.PSPath
$enabled = (Get-ItemProperty -Path "`$path\Server" -Name Enabled -ErrorAction SilentlyContinue).Enabled
Write-Host "`$protocol : `$enabled"
}
# # Enable TLS 1.2 server sideNew-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" -Name Enabled -Value 1 -PropertyType DWORD -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" -Name DisabledByDefault -Value 0 -PropertyType DWORD -Force
# # Enable TLS 1.2 client sideNew-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" -Name Enabled -Value 1 -PropertyType DWORD -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" -Name DisabledByDefault -Value 0 -PropertyType DWORD -Force
# # Disable insecure protocols (SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1)$protocols = @("SSL 2.0", "SSL 3.0", "TLS 1.0", "TLS 1.1")
foreach ($protocol in $protocols) {
New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\`$protocol\Server" -Force | Out-Null
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\`$protocol\Server" -Name Enabled -Value 0 -PropertyType DWORD -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\`$protocol\Server" -Name DisabledByDefault -Value 1 -PropertyType DWORD -Force
}
# # Restart server to apply configurationRestart-Computer
# # Windows Server 2019+ supports TLS 1.3# # Enable TLS 1.3 (requires Windows update support)New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server" -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server" -Name Enabled -Value 1 -PropertyType DWORD -Force
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server" -Name DisabledByDefault -Value 0 -PropertyType DWORD -Force
# 重启服务器
Restart-Computer
Need to install IIS URL Rewrite module (all IIS versions support):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
# # Check IIS versionGet-ItemProperty "HKLM:\SOFTWARE\Microsoft\InetStp" | Select-Object MajorVersion, MinorVersion
# # Or use command line%windir%\system32\inetsrv\appcmd.exe list config /section:system.webServer
# # List all SSL bindingsGet-ChildItem IIS:\SslBindings
# # View bindings for specific siteGet-WebBinding -Name "YourSiteName" -Protocol https
# # View certificate detailed informationGet-ChildItem -Path Cert:\LocalMachine\My | Format-List Subject, Thumbprint, NotAfter
Intermediate certificate missing in certificate chainCertificate private key not foundThis site cannot provide a secure connectionSNI binding failed# # Use online tools to verifyhttps://www.ssllabs.com/ssltest/
https://myssl.com/
# # Use PowerShell to test connectionTest-NetConnection -ComputerName yourdomain.com -Port 443
# # Use OpenSSL to testopenssl s_client -connect yourdomain.com:443 -servername yourdomain.com
# # IIS log default locationC:\inetpub\logs\LogFiles\
# # Use PowerShell to view recent errorsGet-Content "C:\inetpub\logs\LogFiles\W3SVC*\*.log" -Tail 50 | Select-String "error"