How to Configure TLS/SSL in IIS on Windows Server 2012 R2

Properly configuring TLS/SSL in Internet Information Services (IIS) on Windows Server 2012 R2 is essential for protecting data in transit for web applications, APIs, and services. The default IIS configuration on Server 2012 R2 supports SSL 2.0, SSL 3.0, and TLS 1.0 — all of which have known vulnerabilities (POODLE, BEAST, DROWN). A hardened TLS configuration disables legacy protocols and weak cipher suites, enforces TLS 1.1 and TLS 1.2 as minimum versions, configures strong cipher suites in an appropriate order, and enables HTTP Strict Transport Security (HSTS). This guide covers certificate binding, protocol hardening, cipher suite configuration, and security best practices for IIS on Server 2012 R2.

Prerequisites

IIS must be installed on Windows Server 2012 R2. An SSL certificate — either from a commercial CA or an internal CA trusted by all clients — must be installed in the Local Computer Personal certificate store. The certificate’s CN or SAN must match the hostname clients will use to access the site. You need local Administrator rights. For the cipher suite configuration, changes are made in the Windows registry and require a server restart to take effect. Test TLS changes in a non-production environment first, and keep an alternative access method (console, IPMI) available in case IIS becomes unreachable after configuration changes.

Installing IIS with SSL Support

# Install IIS with HTTPS and management tools
Install-WindowsFeature Web-Server -IncludeManagementTools
Install-WindowsFeature Web-Ssl-Certificate-Store
Install-WindowsFeature Web-Cert-Auth

# Verify installation
Get-WindowsFeature Web-Server, Web-Ssl-Certificate-Store | 
    Select-Object Name, InstallState

Installing and Binding the SSL Certificate

Import the SSL certificate and bind it to the IIS site:

# Import PFX certificate to Local Computer Personal store
$CertPassword = ConvertTo-SecureString "CertPFXPassword123!" -AsPlainText -Force
$Cert = Import-PfxCertificate -FilePath "C:Certswww.contoso.com.pfx" `
    -CertStoreLocation "Cert:LocalMachineMy" `
    -Password $CertPassword

Write-Host "Certificate imported. Thumbprint: $($Cert.Thumbprint)"

# Create HTTPS binding on the Default Web Site
New-WebBinding -Name "Default Web Site" `
    -Protocol https `
    -Port 443 `
    -HostHeader "www.contoso.com" `
    -SslFlags 1  # 0=default, 1=SNI, 2=CentralCert, 3=SNI+CentralCert

# Bind the certificate to the HTTPS binding
$Binding = Get-WebBinding -Name "Default Web Site" -Protocol https
$Binding.AddSslCertificate($Cert.Thumbprint, "My")

# Verify the binding was created
Get-WebBinding -Name "Default Web Site" | Select-Object protocol, bindingInformation | Format-Table

For multiple certificates on the same IP/port, use Server Name Indication (SNI):

# Bind certificate using SNI (allows multiple SSL certs per IP)
# After creating the binding with SslFlags=1 (SNI), bind via netsh
netsh http add sslcert hostnameport="www.contoso.com:443" `
    certhash=$($Cert.Thumbprint) `
    appid="{4DC3E181-E14B-4a21-B022-59FC669B0914}" `
    certstorename=MY

# Verify all SSL certificate bindings
netsh http show sslcert

Disabling Weak SSL/TLS Protocols

Windows Server 2012 R2 enables SSL 2.0, SSL 3.0, and TLS 1.0 by default. Disable all versions below TLS 1.1 via the registry. These changes require a restart:

# Disable SSL 2.0
New-Item -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 2.0Server" -Force
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 2.0Server" `
    -Name "Enabled" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 2.0Server" `
    -Name "DisabledByDefault" -Value 1 -Type DWord

# Disable SSL 3.0 (POODLE vulnerability)
New-Item -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 3.0Server" -Force
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 3.0Server" `
    -Name "Enabled" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 3.0Server" `
    -Name "DisabledByDefault" -Value 1 -Type DWord

# Disable TLS 1.0 (required for PCI DSS 3.2+ compliance)
New-Item -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server" -Force
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server" `
    -Name "Enabled" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server" `
    -Name "DisabledByDefault" -Value 1 -Type DWord

# Enable TLS 1.1
New-Item -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.1Server" -Force
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.1Server" `
    -Name "Enabled" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.1Server" `
    -Name "DisabledByDefault" -Value 0 -Type DWord

# Enable TLS 1.2 (primary protocol)
New-Item -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.2Server" -Force
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.2Server" `
    -Name "Enabled" -Value 1 -Type DWord
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.2Server" `
    -Name "DisabledByDefault" -Value 0 -Type DWord

Disabling Weak Cipher Suites

Disable weak cipher suites including RC4, DES, 3DES, and NULL ciphers, and disable MD5/SHA1-based HMAC:

# Disable RC4 cipher (multiple CVEs)
$RC4KeyPath = "HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELCiphers"
"RC4 40/128","RC4 56/128","RC4 64/128","RC4 128/128" | ForEach-Object {
    New-Item -Path "$RC4KeyPath$_" -Force
    Set-ItemProperty -Path "$RC4KeyPath$_" -Name "Enabled" -Value 0 -Type DWord
}

# Disable DES and 3DES
"DES 56/56","Triple DES 168" | ForEach-Object {
    New-Item -Path "$RC4KeyPath$_" -Force
    Set-ItemProperty -Path "$RC4KeyPath$_" -Name "Enabled" -Value 0 -Type DWord
}

# Disable NULL cipher
New-Item -Path "$RC4KeyPathNULL" -Force
Set-ItemProperty -Path "$RC4KeyPathNULL" -Name "Enabled" -Value 0 -Type DWord

# Enable AES 128 and 256
"AES 128/128","AES 256/256" | ForEach-Object {
    New-Item -Path "$RC4KeyPath$_" -Force
    Set-ItemProperty -Path "$RC4KeyPath$_" -Name "Enabled" -Value 0xffffffff -Type DWord
}

Configuring the Cipher Suite Order

Configure the TLS cipher suite priority order to prefer forward secrecy (ECDHE/DHE) and AES-GCM cipher suites:

# Set the preferred cipher suite order via Group Policy or registry
# These suites prioritize ECDHE (Perfect Forward Secrecy) and AES-256-GCM

$CipherSuites = @(
    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
    "TLS_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_RSA_WITH_AES_256_CBC_SHA256",
    "TLS_RSA_WITH_AES_128_CBC_SHA256"
)

$CipherString = $CipherSuites -join ","

# Apply via Group Policy (Computer Config > Admin Templates > Network > SSL Config Settings)
# "SSL Cipher Suite Order" = enabled with the cipher suite list above

# Or via registry:
Set-ItemProperty -Path "HKLM:SOFTWAREPoliciesMicrosoftCryptographyConfigurationSSL0010002" `
    -Name "Functions" -Value $CipherString -Type String

Configuring HTTP to HTTPS Redirect

Redirect all HTTP traffic to HTTPS to ensure users always use encrypted connections:

# Install URL Rewrite module first (requires separate download: IIS URL Rewrite 2.1)
# After installation, configure via PowerShell or web.config

# Redirect HTTP to HTTPS via web.config
$WebConfigPath = "C:inetpubwwwrootweb.config"
$RewriteRule = @"


    
        
            
                
                    
                    
                        
                    
                    
                
            
        
    

"@
$RewriteRule | Out-File $WebConfigPath -Encoding UTF8

Configuring HTTP Strict Transport Security (HSTS)

HSTS instructs browsers to only connect using HTTPS for a specified period, preventing protocol downgrade attacks:

# Add HSTS header to IIS response via HTTP Response Headers
# In IIS Manager: Site > HTTP Response Headers > Add
# Name: Strict-Transport-Security
# Value: max-age=31536000; includeSubDomains

# Via PowerShell (requires IIS module)
Import-Module WebAdministration

# Add HSTS header to Default Web Site
Add-WebConfigurationProperty -PSPath "IIS:SitesDefault Web Site" `
    -Filter "system.webServer/httpProtocol/customHeaders" `
    -Name "." `
    -Value @{name="Strict-Transport-Security"; value="max-age=31536000; includeSubDomains; preload"}

# Add other security headers while here
Add-WebConfigurationProperty -PSPath "IIS:SitesDefault Web Site" `
    -Filter "system.webServer/httpProtocol/customHeaders" `
    -Name "." `
    -Value @{name="X-Content-Type-Options"; value="nosniff"}

Add-WebConfigurationProperty -PSPath "IIS:SitesDefault Web Site" `
    -Filter "system.webServer/httpProtocol/customHeaders" `
    -Name "." `
    -Value @{name="X-Frame-Options"; value="SAMEORIGIN"}

Verification with SSL Testing Tools

# Test TLS configuration from PowerShell
# Check which TLS protocols the server accepts
$Protocols = @("SSL2","SSL3","TLS","TLS11","TLS12")
foreach ($Protocol in $Protocols) {
    try {
        $TcpClient = New-Object System.Net.Sockets.TcpClient
        $TcpClient.Connect("localhost", 443)
        $Stream = New-Object System.Net.Security.SslStream($TcpClient.GetStream())
        $Stream.AuthenticateAsClient("localhost", $null, [System.Security.Authentication.SslProtocols]::$Protocol, $false)
        Write-Host "$Protocol : SUPPORTED" -ForegroundColor Red
    } catch {
        Write-Host "$Protocol : DISABLED" -ForegroundColor Green
    } finally {
        if ($Stream) { $Stream.Close() }
        if ($TcpClient) { $TcpClient.Close() }
    }
}

# View current SSL certificate binding
netsh http show sslcert

# Check IIS bindings
Get-WebBinding | Select-Object protocol, bindingInformation, sslFlags | Format-Table

Summary

A secure TLS/SSL configuration for IIS on Windows Server 2012 R2 requires multiple layers of hardening: binding a strong certificate to the HTTPS site binding using SNI for multi-site deployments, disabling SSL 2.0, SSL 3.0, and TLS 1.0 via SCHANNEL registry settings, disabling RC4, DES, and NULL ciphers, configuring the cipher suite order to prioritize ECDHE-based suites with AES-256-GCM for perfect forward secrecy, redirecting HTTP to HTTPS, and implementing HSTS to prevent downgrade attacks. After applying all registry changes, restart the server to ensure SCHANNEL picks up the new protocol and cipher settings. Use an SSL testing tool to validate the configuration before deploying to production.