配置 TLS 1.3

适用于: SQL Server 2022 (16.x) 及更高版本

本文介绍如何执行以下操作:

  1. 对 SQL Server 2022 (16.x) 实例进行配置以使用传输层安全性 (TLS) 1.3 和 TLS 1.2
  2. 验证协议是否正常运行
  3. 禁用不安全的旧版协议,包括 TLS 1.0 和 1.1

要求

要在 SQL Server 2022 (16.x) 中支持 TLS 1.3,需要满足以下条件:

  • Windows Server 2022
  • 已安装累积更新 1 的 SQL Server 2022 (16.x) 或更高版本
  • SQL Server 实例使用 TCP/IP 作为网络协议
  • 随其私钥一起安装的有效 X.509 服务器证书

重要

本文档假定你在短期内将同时需要 TLS 1.3 和 TLS 1.2,而在长期将仅需要 TLS 1.3。

SQL Server 和 TLS

SQL Server 本身并不执行 TLS 操作,而是由 Windows 使用 Schannel SSP 来执行这项工作。 Schannel 是一个安全支持提供程序 (SSP),其中包含并公开 Microsoft 对 Internet 标准安全协议(如 TLS)的实现。 Schannel 对于 Windows 的作用就好比 OpenSSL 对于 Linux。

要为 SQL Server 配置 TLS,你需要为 Windows 配置 TLS。

对于 Windows Server 2022 上的 SQL Server 2022 (16.x),SQL Server 支持 TLS 1.0、1.1、1.2 和 1.3。 要验证这一点,请使用 GitHub at TlsTest 中提供的 .NET 代码。 此工具的输出如下所示:

Trying Ssl2
Authentication failed, see inner exception.
Exception: The client and server cannot communicate, because they do not possess a common algorithm.
Trying Ssl3
Authentication failed, see inner exception.
Exception: The client and server cannot communicate, because they do not possess a common algorithm.
Trying Tls
Tls using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Trying Tls11
Tls11 using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Trying Tls12
Tls12 using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Trying Tls13
Tls13 using TLS_AES_256_GCM_SHA384

将 Windows 配置为仅使用 TLS 1.2 和 TLS 1.3

Windows 在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL 下有一组注册表项,用来控制 TLS 协议版本和密码套件。 对于此场景,仅影响服务器的协议版本很重要,因为 SQL Server 实例会充当服务器。

以下 PowerShell 脚本将更新注册表,以便在服务器使用时启用或禁用 TLS 1.0 和 TLS 1.1:

警告

请首先备份注册表,然后再继续操作。 这将有利于在未来还原注册表(如有必要)。

# Learn more at https://learn.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings?tabs=diffie-hellman
Set-StrictMode -Version Latest

$base = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\'
$protocols = [ordered]@{
    "SSL 2.0" = $false
    "SSL 3.0" = $false
    "TLS 1.0" = $false
    "TLS 1.1" = $false
    "TLS 1.2" = $true
    "TLS 1.3" = $true
}

foreach ($version in $protocols.Keys) {

    $enabledValue = $protocols[$version]
    $path = $base + $version + '\Server'

    New-Item $path -Force | Out-Null
    New-ItemProperty -Path $path `
                     -Name 'Enabled' `
                     -Value $enabledValue `
                     -PropertyType 'DWord' `
                     -Force | Out-Null
                     
    Write-Host "$version is $enabledValue."
}

GitHub 中提供了此代码。

运行此脚本后,重启 SQL Server 进程,以使新的 TLS 设置生效。 如果现在运行本文开头提及的代码,则将返回如下消息:

Trying Ssl2
Authentication failed, see inner exception.
Exception: The client and server cannot communicate, because they do not possess a common algorithm.
Trying Ssl3
Authentication failed, see inner exception.
Exception: The client and server cannot communicate, because they do not possess a common algorithm.
Trying Tls
Received an unexpected EOF    or 0 bytes from the transport stream.
Exception:
Trying Tls11
Received an unexpected EOF or 0 bytes from the transport stream.
Exception:
Trying Tls12
Tls12 using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Trying Tls13
Tls13 using TLS_AES_256_GCM_SHA384

请注意,SSL 2.0、SSL 3.0、TLS 1.0 和 TLS 1.1 都无法连接,但 TLS 1.2 和 TLS 1.3 都能成功连接。

注册表更新后,Windows 以及此 SQL Server 实例将仅允许 TLS 1.2 和 TLS 1.3 连接。 以后,随着更多客户端支持 TLS 1.3,还可以禁用 TLS 1.2。

设置 SQL Server 实例以强制实施严格加密

最后一步是将实例设置为使用 Force Strict Encryption。 使用 Force Strict Encryption 时,SQL 实例将使用受支持版本的表格格式数据流(TDS 8.0 或更高版本)。

使用 SQL Server 配置管理器设置此设置。

  1. 展开“SQL Server 网络配置”

  2. 右键单击“<instance name> 的协议”,然后选择“属性”

    默认实例名为 MSSQLSERVER

  3. 在“标志”选项卡上,将“强制实施严格加密”设置为“是”

    SQL Server 配置管理器“配置协议”对话框的 UI 控件的屏幕截图。

验证安全性

本节演示如何使用 Wireshark、OpenSSL 和 Nmap 验证加密。

Wireshark

可以使用网络探查器来确定 TLS 协议版本和商定的密码套件。 你可能会发现一些数据令人困惑。 如果从 Wireshark 分析下面的屏幕截图,则会显示数据包是 TLS v1.3 记录层,但协议版本为 TLS 1.2,握手协议版本也是 TLS 1.2。 这些都是 TLS 1.2 规范的一部分,正确且符合预期。 商定的协议版本位于“扩展”部分中,在这里可以看出“支持的版本”是 TLS 1.3。

TLS 扩展部分的屏幕截图。

OpenSSL

还可以使用 openssl 发现商定的 TLS 信息。

使用以下命令:

openssl s_client 127.0.0.1:1433

该命令将返回类似下面的结果:

Post-Handshake New Session Ticket arrived:
SSL-Session:
   Protocol   : TLSv1.3
   Cipher     : TLS_AES_256_GCM_SHA384
   Session-ID : 516D56D99088BCDE1 <snip> 098EDB1A
   Session-ID-ctx:
   Resumption PSD: B2B9CB92B59aa1 <snip> BD824CBA
   PSK identity: None

Nmap

Nmap 的当前版本是版本 7.94,似乎在使用以下参数时未检测到 TLS 1.3:

nmap -sV --script ssl-enum-ciphers -p 1433 127.0.0.1