This is a living document - check back from time to time.

This PowerShell script setups your Windows Computer to support TLS 1.1 and TLS 1.2 protocol with Forward secrecy. Additionally it increases security of your SSL connections by disabling insecure SSL2 and SSL3 and all insecure and weak ciphers that a browser may fall-back, too. This script implements the current best practice rules. It was originally written for Microsoft Internet Information Server 7.5/8.0/8.5/10 (IIS) on Windows 2008R2/2012/2012R2/2016/2019, but the below settings implements system wide settings that work for everything that uses the Microsoft Crypto infrastructure. This means Microsoft Exchange and Internet Explorer and Edge and all applications that use WinHTTP API, too. It works on both Windows Desktops and Servers.

Please note that perfect forward secrecy is the only way to prevent hackers or intelligence services to decrypt your SSL data after traffic shaping. Always keep in mind that decrypting of todays SSL traffic could also been done in a few years if computers are fast enough to break today's certificates. As IIS user you are not affected by the Heartbleed bug in OpenSSL, but we all hope Microsoft schannel.dll does not have any similar bugs. Forward secrecy also makes it impossible to decrypt the SSL traffic if your private key may has been stolen or lost or your US company is enforced by a national security letter to shut up and give them your private key. Stealing the private key was quite easy with Heartbleed and we can only guess how many Apache servers are still out there with this security hole open. Only Apache 2.4 with latest OpenSSL 1.0.1x can fully support forward secrecy. Until end of year 2014 nearly all stable Linux distributions had Apache 2.2 only embedded and upgrading to 2.4 is very difficult nor impossible. On 25 May 2014 Debian backported ECDH ciphers (apache2_2.2.22-13+deb7u4_changelog) to work with Apache 2.2, and it's now possible to enable PFS! If you are looking for a secure Apache configuration see Mozilla SSL Configuration Generator, please. Running your SSL sites without forward secrecy enabled can be seen as critical security risk.

After you have added below registry entries you may like to verify that your server offers the much more secure SSL connections. There is the great https://www.ssllabs.com/ssltest/ site that gives you a feeling how secure your SSL connections are. You should get a Summary like this:

The detailed browsers list should show everywhere Perfect Forward Secrecy (FS). As example see the TLS 1.2 only test results of Windows 2016 with HTTP2 enabled:

Windows XP with IE6/8 does not support Forward Secrecy just as a note. If you still need to support Windows XP with Internet Explorer 8 because of relatively high usage (e.g. ~10%, November 2014) you cannot disable both RC4 and 3DES ciphers. The latest 1.x script version disables RC4, but leaves 3DES enabled to support Windows XP. More information about this can be found at IE Supported Cipher Suites. Script versions 2.x and later no longer support Windows XP.

This are the Cipher Suites enabled in Windows 2016 with Script 3.x.

You can also tell the browser to never visit HTTP links on your site by enabling HSTS. To enable HTTP Strict Transport Security (HSTS) under IIS you need to install an extra module to comply with RFC standards. You cannot simply add the header as this must only send on HTTPS, but not HTTP. In older versions of IIS (IIS 7.0 to 10.0 R1703) this requirement can only archived the simple way with an installation of HTTP Strict Transport Security IIS Module. Other solutions like two independed websites or HTTP Redirect Module + Custom Headers are challenging configurations. In the meantime Microsoft added native HTTP Strict Transport Security (HSTS) Support to IIS 10.0 Version 1709 and later that simplifies the process a lot. It is typically recommended to set HSTS header to max-age value 15768000 (6 months) on SSL only websites. This should result in an increased A+ rating at SSLLabs what is the very best you can achieve, but since a change in October 2014 this seems to require Windows 2016 or later with TLS_FALLBACK_SCSV support.

Known issues:

02.07.2020: Dell EMC iDRAC-Service-Modul seems to have issues connecting from server host to iDRAC with strong SSL settings implemented in versions higher than 2.x. Looks like they require outdated MD5 + 3DES per development testing. Hopefully they can change this soon as weaken security is no useful option. Its better to remove Dell iSM than.

Other notes:

HTTP2 requires Windows 2016 with IIS 10 or later. Earlier Windows versions do not provide HTTP2 support and it may never get backported from Microsoft. If you install Windows 2016 with IIS 10 and the client browser supports HTTP2 these new protocol will be used automatically. If the client does not support HTTP2 it will automatically fallback to earlier versions. Web browsers are using HTTP2 only on SSL connections as of now. For all the people who have disabled HTTP2 because of a chunking bug in HTTP.sys that can be seen with Tomcat servers, there will be a fix included in Windows Rollup - April 2018 that resolves this serious Windows bug.

TLS 1.3 is not yet available in Microsoft IIS 10 (July 2020). Do not expect that this script can enable it if the operating system does not support it, please. https://devblogs.microsoft.com/premier-developer/microsoft-tls-1-3-support-reference/

If Microsoft Office applications open documents from a SharePoint library or a Web Folder, IP-HTTPS tunnels for DirectAccess connectivity, and other applications by using technologies such as WebClient by using WebDav, WinRM, and others the connection may fail. See Update to enable TLS 1.1 and TLS 1.2 as a default secure protocols in WinHTTP in Windows for the solution. Script versions v1.9 and later will enable it automatically.

.NET 3.5 and .NET 4.0 by default are not using the SCHANNEL settings configured here, but with script versions v1.9 and later this will be enabled. .NET 4.7 and later will also use the SCHANNEL OS settings, see Transport Layer Security (TLS) best practices with the .NET Framework.

If you ever wished to create statistics about encryption protocol versions and ciphers your clients are using, see New IIS functionality to help identify weak TLS usage how this can be logged in Windows Server 2016 and Windows Server 2012 R2 IIS logs.

Microsoft Exchange 2010/2013: Do not use script versions later than v2.x. If TLS 1.0 get's disabled with v1.10 or later there are a lot of things that may break. It is not clear if MS will backport required changes as of today as they still work on fixing Exchange 2016 (June 2018).

Microsoft Exchange 2016: You can use v1.10 or higher, but you need to install latest Exchange rollup hotfix (minimum May 2018) and NET 4.7.2 will be mandatory soon.

Windows Update Server (WSUS): If you use SSL for WSUS updates you also need to make sure the WSUS server has TLS 1.2 enabled. Otherwise the client fails to report status and to download updates. You should at minimum run v1.x script on WSUS servers to enable TLS 1.1 and TLS 1.2 if you may need to support TLS 1.0 clients. At the best you keep all clients and servers in sync with the same script version.

PCI DSS 3.1 rules are implemented in v1.10 or higher.

This script was created to show what settings will be changed. The intention is to hide nothing from your eyes in a closed source windows application that just do some voodoo to your machine.

Powershell script to configure your IIS server with Perfect Forward Secrecy and TLS 1.2:

# Copyright 2019, Alexander Hass # https://www.hass.de/content/setup-microsoft-windows-or-iis-ssl-perfect-forward-secrecy-and-tls-12 # # After running this script the computer only supports: # - TLS 1.2 # # Version 3.0.1, see CHANGELOG.txt for changes. Write-Host 'Configuring IIS with SSL/TLS Deployment Best Practices...' Write-Host '--------------------------------------------------------------------------------' # Disable Multi-Protocol Unified Hello New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\Multi-Protocol Unified Hello\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\Multi-Protocol Unified Hello\Server' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\Multi-Protocol Unified Hello\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\Multi-Protocol Unified Hello\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\Multi-Protocol Unified Hello\Client' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\Multi-Protocol Unified Hello\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null Write-Host 'Multi-Protocol Unified Hello has been disabled.' # Disable PCT 1.0 New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Server' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Client' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null Write-Host 'PCT 1.0 has been disabled.' # Disable SSL 2.0 (PCI Compliance) New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null Write-Host 'SSL 2.0 has been disabled.' # NOTE: If you disable SSL 3.0 the you may lock out some people still using # Windows XP with IE6/7. Without SSL 3.0 enabled, there is no protocol available # for these people to fall back. Safer shopping certifications may require that # you disable SSLv3. # # Disable SSL 3.0 (PCI Compliance) and enable "Poodle" protection New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null Write-Host 'SSL 3.0 has been disabled.' # Disable TLS 1.0 for client and server SCHANNEL communications New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -name 'Enabled' -value '0' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client' -name 'Enabled' -value '0' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null Write-Host 'TLS 1.0 has been disabled.' # Add and Disable TLS 1.1 for client and server SCHANNEL communications New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -name 'Enabled' -value '0' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client' -name 'Enabled' -value '0' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client' -name 'DisabledByDefault' -value 1 -PropertyType 'DWord' -Force | Out-Null Write-Host 'TLS 1.1 has been disabled.' # Add and Enable TLS 1.2 for client and server SCHANNEL communications New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '0xffffffff' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value '0xffffffff' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null Write-Host 'TLS 1.2 has been enabled.' # Re-create the ciphers key. New-Item 'HKLM:SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers' -Force | Out-Null # Disable insecure/weak ciphers. $insecureCiphers = @ ( 'DES 56/56' , 'NULL' , 'RC2 128/128' , 'RC2 40/128' , 'RC2 56/128' , 'RC4 40/128' , 'RC4 56/128' , 'RC4 64/128' , 'RC4 128/128' , 'Triple DES 168' ) Foreach ( $insecureCipher in $insecureCiphers ) { $key = ( Get-Item HKLM:\ ) .OpenSubKey ( 'SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers' , $true ) .CreateSubKey ( $insecureCipher ) $key .SetValue ( 'Enabled' , 0 , 'DWord' ) $key .close ( ) Write-Host "Weak cipher $insecureCipher has been disabled." } # Enable new secure ciphers. # - RC4: It is recommended to disable RC4, but you may lock out WinXP/IE8 if you enforce this. This is a requirement for FIPS 140-2. # - 3DES: It is recommended to disable these in near future. This is the last cipher supported by Windows XP. # - Windows Vista and before 'Triple DES 168' was named 'Triple DES 168/168' per https://support.microsoft.com/en-us/kb/245030 $secureCiphers = @ ( 'AES 128/128' , 'AES 256/256' ) Foreach ( $secureCipher in $secureCiphers ) { $key = ( Get-Item HKLM:\ ) .OpenSubKey ( 'SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers' , $true ) .CreateSubKey ( $secureCipher ) New-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\$secureCipher" -name 'Enabled' -value '0xffffffff' -PropertyType 'DWord' -Force | Out-Null $key .close ( ) Write-Host "Strong cipher $secureCipher has been enabled." } # Set hashes configuration. New-Item 'HKLM:SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes' -Force | Out-Null New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes\MD5' -Force | Out-Null New-ItemProperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes\MD5' -name Enabled -value 0 -PropertyType 'DWord' -Force | Out-Null $secureHashes = @ ( 'SHA' , 'SHA256' , 'SHA384' , 'SHA512' ) Foreach ( $secureHash in $secureHashes ) { $key = ( Get-Item HKLM:\ ) .OpenSubKey ( 'SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes' , $true ) .CreateSubKey ( $secureHash ) New-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes\$secureHash" -name 'Enabled' -value '0xffffffff' -PropertyType 'DWord' -Force | Out-Null $key .close ( ) Write-Host "Hash $secureHash has been enabled." } # Set KeyExchangeAlgorithms configuration. New-Item 'HKLM:SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms' -Force | Out-Null $secureKeyExchangeAlgorithms = @ ( 'Diffie-Hellman' , 'ECDH' , 'PKCS' ) Foreach ( $secureKeyExchangeAlgorithm in $secureKeyExchangeAlgorithms ) { $key = ( Get-Item HKLM:\ ) .OpenSubKey ( 'SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms' , $true ) .CreateSubKey ( $secureKeyExchangeAlgorithm ) New-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\$secureKeyExchangeAlgorithm" -name 'Enabled' -value '0xffffffff' -PropertyType 'DWord' -Force | Out-Null $key .close ( ) Write-Host "KeyExchangeAlgorithm $secureKeyExchangeAlgorithm has been enabled." } # Microsoft Security Advisory 3174644 - Updated Support for Diffie-Hellman Key Exchange # https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2016/3174644 Write-Host 'Configure longer DHE key shares for TLS servers.' New-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman" -name 'ServerMinKeyBitLength' -value '2048' -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman" -name 'ClientMinKeyBitLength' -value '2048' -PropertyType 'DWord' -Force | Out-Null # https://support.microsoft.com/en-us/help/3174644/microsoft-security-advisory-updated-support-for-diffie-hellman-key-exc New-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\PKCS" -name 'ClientMinKeyBitLength' -value '2048' -PropertyType 'DWord' -Force | Out-Null # Set cipher suites order as secure as possible (Enables Perfect Forward Secrecy). $os = Get-WmiObject -class Win32_OperatingSystem if ( [ System.Version ] $os .Version -lt [ System.Version ] '10.0' ) { Write-Host 'Use cipher suites order for Windows 2008/2008R2/2012/2012R2.' $cipherSuitesOrder = @ ( 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P521' , 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384' , 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256' , 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P521' , 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384' , 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256' , 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P521' , 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384' , 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256' , 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P521' , 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384' , 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256' , 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P521' , 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P521' , 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P521' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P521' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P521' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P521' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256' , # Below are the only AEAD ciphers available on Windows 2012R2 and earlier. # - RSA certificates need below ciphers, but ECDSA certificates (EV) may not. # - We get penalty for not using AEAD suites with RSA certificates. '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' , 'TLS_RSA_WITH_AES_256_CBC_SHA' , 'TLS_RSA_WITH_AES_128_CBC_SHA' ) } else { Write-Host 'Use cipher suites order for Windows 10/2016 and later.' $cipherSuitesOrder = @ ( '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_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256' , 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA' , 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA' ) } $cipherSuitesAsString = [ string ] ::join ( ',' , $cipherSuitesOrder ) # One user reported this key does not exists on Windows 2012R2. Cannot repro myself on a brand new Windows 2012R2 core machine. Adding this just to be save. New-Item 'HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002' -ErrorAction SilentlyContinue New-ItemProperty -path 'HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002' -name 'Functions' -value $cipherSuitesAsString -PropertyType 'String' -Force | Out-Null # Exchange Server TLS guidance Part 2: Enabling TLS 1.2 and Identifying Clients Not Using It # https://blogs.technet.microsoft.com/exchange/2018/04/02/exchange-server-tls-guidance-part-2-enabling-tls-1-2-and-identifying-clients-not-using-it/ # New IIS functionality to help identify weak TLS usage # https://cloudblogs.microsoft.com/microsoftsecure/2017/09/07/new-iis-functionality-to-help-identify-weak-tls-usage/ Write-Host 'Enable TLS 1.2 for .NET 3.5 and .NET 4.x' New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v2.0.50727" -name 'SystemDefaultTlsVersions' -value 1 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v2.0.50727" -name 'SchUseStrongCrypto' -value 1 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name 'SystemDefaultTlsVersions' -value 1 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name 'SchUseStrongCrypto' -value 1 -PropertyType 'DWord' -Force | Out-Null if ( Test-Path 'HKLM:\SOFTWARE\Wow6432Node' ) { New-ItemProperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727" -name 'SystemDefaultTlsVersions' -value 1 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727" -name 'SchUseStrongCrypto' -value 1 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name 'SystemDefaultTlsVersions' -value 1 -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name 'SchUseStrongCrypto' -value 1 -PropertyType 'DWord' -Force | Out-Null } # DefaultSecureProtocols Value Decimal value Protocol enabled # 0x00000008 8 Enable SSL 2.0 by default # 0x00000020 32 Enable SSL 3.0 by default # 0x00000080 128 Enable TLS 1.0 by default # 0x00000200 512 Enable TLS 1.1 by default # 0x00000800 2048 Enable TLS 1.2 by default $defaultSecureProtocols = @ ( '2048' # TLS 1.2 ) $defaultSecureProtocolsSum = ( $defaultSecureProtocols | Measure-Object -Sum ) .Sum # Update to enable TLS 1.2 as a default secure protocols in WinHTTP in Windows # https://support.microsoft.com/en-us/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-a-default-secure-protocols-in # Verify if hotfix KB3140245 is installed. $file_version_winhttp_dll = ( Get-Item $env :windir\System32\winhttp.dll ) .VersionInfo | % { ( "{0}.{1}.{2}.{3}" -f $_ .ProductMajorPart , $_ .ProductMinorPart , $_ .ProductBuildPart , $_ .ProductPrivatePart ) } $file_version_webio_dll = ( Get-Item $env :windir\System32\Webio.dll ) .VersionInfo | % { ( "{0}.{1}.{2}.{3}" -f $_ .ProductMajorPart , $_ .ProductMinorPart , $_ .ProductBuildPart , $_ .ProductPrivatePart ) } if ( [ System.Version ] $file_version_winhttp_dll -lt [ System.Version ] "6.1.7601.23375" -or [ System.Version ] $file_version_webio_dll -lt [ System.Version ] "6.1.7601.23375" ) { Write-Host 'WinHTTP: Cannot enable TLS 1.2. Please see https://support.microsoft.com/en-us/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-a-default-secure-protocols-in for system requirements.' } else { Write-Host 'WinHTTP: Minimum system requirements are met.' Write-Host 'WinHTTP: Activate TLS 1.2 only.' New-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp' -name 'DefaultSecureProtocols' -value $defaultSecureProtocolsSum -PropertyType 'DWord' -Force | Out-Null if ( Test-Path 'HKLM:\SOFTWARE\Wow6432Node' ) { # WinHttp key seems missing in Windows 2019 for unknown reasons. New-Item 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp' -ErrorAction SilentlyContinue | Out-Null New-ItemProperty -path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp' -name 'DefaultSecureProtocols' -value $defaultSecureProtocolsSum -PropertyType 'DWord' -Force | Out-Null } } Write-Host 'Windows Internet Explorer: Activate TLS 1.2 only.' New-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name 'SecureProtocols' -value $defaultSecureProtocolsSum -PropertyType 'DWord' -Force | Out-Null New-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings' -name 'SecureProtocols' -value $defaultSecureProtocolsSum -PropertyType 'DWord' -Force | Out-Null Write-Host '--------------------------------------------------------------------------------' Write-Host 'NOTE: After the system has been rebooted you can verify your server' Write-Host ' configuration at https://www.ssllabs.com/ssltest/' Write-Host "-------------------------------------------------------------------------------- `n " Write-Host -ForegroundColor Red 'A computer restart is required to apply settings. Restart computer now?' Restart - Computer -Force -Confirm

History