SQL Server 2016:为SQL Server连接启用TLS 1.2

9
我有一台运行在Windows 2012 R2上的SQL Server 2016,并应用了TLSv1.2支持补丁并重新启动了虚拟机。https://support.microsoft.com/en-us/help/3135244/tls-1-2-support-for-microsoft-sql-server 我使用IISCrypto工具在SQL Server VM上看到TLS 1.2已启用。
我们有一个Java 8 Web应用程序,我们强制该Web应用程序仅使用JVM参数-Djdk.tls.client.protocols="TLSv1.2"使用TLS1.2(如果我删除此JVM参数,则应用程序可以正常连接到SQL Server),但是我们仍然看到以下错误,尽管SQL服务器启用了TLSv1.2
org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "Server chose TLSv1, but that protocol version is not enabled or not supported by the client.". ClientConnectionId:7564b6a1-60c0-4a24-8baa-7bd21f9512cf)  

我们还有一个基于.Net 2.0的Windows服务(仅在注册表中启用TLSv1.2),也无法连接到SQL Server 2016
System.Data.OleDb.OleDbException: [DBNETLIB][ConnectionOpen (SECCreateCredentials()).]SSL Security error.
at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.OleDb.OleDbConnection.Open()

但如果我在注册表中启用SSL3和TLS1.0,.Net 2.0 Windows服务可以正常连接到SQL Server 2016。

我怀疑问题是SQL Server没有使用TLSv1.2,尽管TLSv1.2已在SQL Server VM上启用,如果有其他配置或补丁需要应用于SQL Server以支持TLSv1.2,请问有人能帮忙吗?


1
你提到的链接说,为了让1.2版本正常工作,必须在服务器的注册表中禁用1.0和1.1版本。与其使用IISCrypto工具,为什么不检查服务器的实际注册表设置,并验证1.0和1.1是否已被禁用,1.2是否已启用呢? - JJF
@RanPaul,您能否尝试一下我在下面回答中提供的方法,并告诉我它是否有效?先谢谢了。 - Murat Yıldız
@RanPaul,已经有答案了吗? - 3per
2个回答

5

Microsoft Windows Server会存储关于Windows Server支持的不同安全增强通道协议的信息。这些信息存储在以下注册表键中:

HKey_Local_Machine\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols

通常,此键包含以下子键:

PCT 1.0、SSL 2.0、SSL 3.0、TLS 1.0 ...

每个键都包含有关该键的协议的信息。可以在服务器上启用其中任何一种协议。为此,请在协议的服务器子键中创建一个新的DWORD值。将DWORD值设置为"1"。

重要提示: 修改注册表之前请备份注册表。如果出现问题,您可以还原注册表。

若要启用TLS 1.x协议,请执行以下步骤:

单击“开始”菜单,单击“运行”,输入regedt32或regedit,然后单击“确定”。 在注册表编辑器中,找到以下注册表键:

HKey_Local_Machine\System\CurrentControlSet\Control\SecurityProviders \SCHANNEL\Protocols\TLS 1.x\Server

在“编辑”菜单上,单击“添加值”。 在“数据类型”列表中,单击“DWORD”。 在“值名称”框中,键入“Enabled”,然后单击“确定”。

注意: 如果存在该值,请双击该值以编辑其当前值。

在二进制编辑器中输入11111111,将新键的值设置为"1"。 单击“确定”。重新启动计算机。


3

请检查涉及的证书,其中可能有失效的。

如果机器已经验证了它们的证书,请尝试:

禁用愚蠢加密的注册表脚本: 将此文件保存为.reg格式

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server]
"Enabled"=dword:00000000
"DisabledByDefault"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client]
"Enabled"=dword:00000001
"DisabledByDefault"=dword:00000000
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server]
"Enabled"=dword:00000001
"DisabledByDefault"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

您需要调整您的.NET Framework。如果您实际上正在使用 .Net 2.0(旧版本!),那么最后两个 Keys 应该是:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001 

这里有一个由Chris Duck编写的.ps1脚本,用于检查启用的加密方式。
    <#
 .DESCRIPTION
   Outputs the SSL protocols that the client is able to successfully use to connect to a server.

 .NOTES

   Copyright 2014 Chris Duck
   http://blog.whatsupduck.net

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 .PARAMETER ComputerName
   The name of the remote computer to connect to.

 .PARAMETER Port
   The remote port to connect to. The default is 443.

 .EXAMPLE
   Test-SslProtocols -ComputerName "www.google.com"

   ComputerName       : www.google.com
   Port               : 443
   KeyLength          : 2048
   SignatureAlgorithm : rsa-sha1
   Ssl2               : False
   Ssl3               : True
   Tls                : True
   Tls11              : True
   Tls12              : True
 #>
 function Test-SslProtocols {
   param(
     [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
     $ComputerName,

     [Parameter(ValueFromPipelineByPropertyName=$true)]
     [int]$Port = 443
   )
   begin {
     $ProtocolNames = [System.Security.Authentication.SslProtocols] | gm -static -MemberType Property | ?{$_.Name -notin @("Default","None")} | %{$_.Name}
   }
   process {
     $ProtocolStatus = [Ordered]@{}
     $ProtocolStatus.Add("ComputerName", $ComputerName)
     $ProtocolStatus.Add("Port", $Port)
     $ProtocolStatus.Add("KeyLength", $null)
     $ProtocolStatus.Add("SignatureAlgorithm", $null)

     $ProtocolNames | %{
       $ProtocolName = $_
       $Socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.SocketType]::Stream, [System.Net.Sockets.ProtocolType]::Tcp)
       $Socket.Connect($ComputerName, $Port)
       try {
         $NetStream = New-Object System.Net.Sockets.NetworkStream($Socket, $true)
         $SslStream = New-Object System.Net.Security.SslStream($NetStream, $true)
         $SslStream.AuthenticateAsClient($ComputerName,  $null, $ProtocolName, $false )
         $RemoteCertificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]$SslStream.RemoteCertificate
         $ProtocolStatus["KeyLength"] = $RemoteCertificate.PublicKey.Key.KeySize
         $ProtocolStatus["SignatureAlgorithm"] = $RemoteCertificate.SignatureAlgorithm.FriendlyName
         $ProtocolStatus["Certificate"] = $RemoteCertificate
         $ProtocolStatus.Add($ProtocolName, $true)
       } catch  {
         $ProtocolStatus.Add($ProtocolName, $false)
       } finally {
         $SslStream.Close()
       }
     }
     [PSCustomObject]$ProtocolStatus
   }
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接