对 Linux 上的 SQL Server 和容器的 Active Directory 身份验证进行故障排除

适用于: SQL Server - Linux

本文将帮助你对 Linux 和容器上的 SQL Server 的 Active Directory 域服务身份验证问题进行故障排除。 包括成功 Active Directory 配置的先决条件检查和提示,以及常见错误和故障排除步骤的列表。

验证当前配置

在开始故障排除之前,必须先验证当前用户、mssql.conf、服务主体名称 (SPN) 和领域设置。

  1. 使用 kinit 获取或续订 Kerberos TGT(票证授予票证):

    kinit privilegeduser@CONTOSO.COM
    
  2. 运行以下命令,确保运行此命令的用户有权访问 mssql.keytab

    /opt/mssql/bin/mssql-conf validate-ad-config /var/opt/mssql/secrets/mssql.keytab
    

    有关 validate-ad-config 命令的详细信息,请查看有关使用 /opt/mssql/bin/mssql-conf validate-ad-config --help 命令的帮助。

DNS 查找和反向 DNS 查找

  1. 对域名和 NetBIOS 名称的 DNS 查找应返回相同的 IP 地址,该地址通常与域控制器 (DC) 的 IP 地址匹配。 从 SQL Server 主机运行这些命令。

    nslookup contoso
    nslookup contoso.com
    

    如果 IP 地址不匹配,请参阅将 Linux 主机上的 SQL Server 加入到 Active Directory 域,以修复 DNS 查找以及与 DC 的通信。

  2. 针对前面的结果中列出的每个 IP 地址执行反向 DNS (rDNS) 查找。 包括 IPv4 和 IPv6 地址(如果适用)。

    nslookup <IPs returned from the above commands>
    

    所有查找均应返回 <hostname>.contoso.com。 如果情况并非如此,请检查 Active Directory 中创建的 PTR (指针) 记录。

    可能需要与域管理员合作才能让 rDNS 正常工作。 如果无法为返回的所有 IP 地址添加 PTR 条目,还可以将 SQL Server 限制到一部分域控制器。 此更改会影响在主机上使用 krb5.conf 的其他任何服务。

    有关反向 DNS 的详细信息,请参阅什么是反向 DNS?

检查密钥表文件和权限

  1. 检查是否创建了密钥表文件,以及 mssql-conf 是否配置为使用具有适当权限的正确文件。 密钥表必须可供 mssql 用户帐户访问。 有关详细信息,请参阅使用 adutil 为 Linux 上的 SQL Server 配置 Active Directory 身份验证

  2. 确保可以列出密钥表的内容,并且已添加正确的 SPN、端口、加密类型和用户帐户。 如果在创建 SPN 和密钥表条目时未正确键入密码,则尝试使用 Active Directory 身份验证登录时会遇到错误。

    klist -kte /var/opt/mssql/secrets/mssql.keytab
    

    下面是一个正常工作的密钥表的示例。 该示例使用两种加密类型,但只能使用一种还是多种加密类型,取决于环境中支持的加密类型。 在此示例中,sqluser@CONTOSO.COM 是特权帐户(与 mssql-conf 中的 network.privilegedadaccount 设置匹配),并且 SQL Server 的主机名是 sqllinux.contoso.com,正在侦听默认端口 1433。

    $ kinit privilegeduser@CONTOSO.COM
    Password for privilegeduser@CONTOSO.COM:
    
    $ klist
    Ticket cache: FILE:/tmp/krb5cc_1000
    Default principal: privilegeduser@CONTOSO.COM
    Valid starting     Expires            Service principal
    01/26/22 20:42:02  01/27/22 06:42:02  krbtgt/CONTOSO.COM@CONTOSO.COM
        renew until 01/27/22 20:41:57
    
    $ klist -kte mssql.keytab
    Keytab name: FILE:mssql.keytab
    KVNO Timestamp         Principal
    ---- ----------------- --------------------------------------------------------
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux@CONTOSO.COM (aes256-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux@CONTOSO.COM (aes128-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux.contoso.com@CONTOSO.COM (aes256-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux.contoso.com@CONTOSO.COM (aes128-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux:1433@CONTOSO.COM (aes256-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux:1433@CONTOSO.COM (aes128-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux.contoso.com:5533@CONTOSO.COM (aes256-cts-hmac-sha1-96)
       2 01/13/22 13:19:47 MSSQLSvc/sqllinux.contoso.com:5533@CONTOSO.COM (aes128-cts-hmac-sha1-96)
       2 01/13/22 13:19:55 sqluser@CONTOSO.COM (aes256-cts-hmac-sha1-96)
       2 01/13/22 13:19:55 sqluser@CONTOSO.COM (aes128-cts-hmac-sha1-96)
    

krb5.conf 中验证领域信息

  1. krb5.conf(位于 /etc/krb5.conf)中,检查是否已为默认领域、领域信息和域到领域映射提供了值。 以下示例是一个示例 krb5.conf 文件。 有关详细信息,请参阅了解 Linux 和容器上 SQL Server 的 Active Directory 身份验证

    [libdefaults]
    default_realm = CONTOSO.COM
    
    [realms]
    CONTOSO.COM = {
        kdc = adVM.contoso.com
        admin_server = adVM.contoso.com
        default_domain= contoso.com
    }
    
    [domain_realm]
    .contoso.com = CONTOSO.COM
    contoso.com = CONTOSO.COM
    
  2. 可以将 SQL Server 限制为联系一部分域控制器,如果 DNS 配置返回的域控制器多于 SQL Server 需要联系的域控制器,这非常有用。 借助 Linux 上的 SQL Server,可以指定 SQL Server 在执行 LDAP 查找时以轮循机制方式联系的域控制器列表。

    你需要完成两个步骤。 首先,通过添加所需的任意数目的域控制器(前缀为 kdc =)修改 krb5.conf

    [realms]
    CONTOSO.COM = {
      kdc = kdc1.contoso.com
      kdc = kdc2.contoso.com
      ..
      ..
    }
    

    请记住,krb5.conf 是一个通用的 Kerberos 客户端配置文件,因此在此文件中进行的任何更改都将影响除 SQL Server 之外的其他服务。 在进行更改之前,请咨询域管理员。

    然后,你可以使用 mssql-conf 启用 network.enablekdcfromkrb5conf 设置,然后重启 SQL Server:

    sudo /opt/mssql/bin/mssql-conf set network.enablekdcfromkrb5conf true
    sudo systemctl restart mssql-server
    

Kerberos 故障排除

请参阅以下详细信息,以帮助你对 Active Directory 身份验证问题进行故障排除,确定具体的错误消息。

跟踪 Kerberos

在创建用户、SPN 和密钥表并配置 mssql-conf 以查看 Linux 上的 Active Directory SQL Server 配置是否正确后,可以使用以下命令,在尝试使用特权帐户获取或续订 Kerberos TGT 时向控制台显示 Kerberos 跟踪消息 (stdout):

root@sqllinux mssql# KRB5_TRACE=/dev/stdout kinit -kt /var/opt/mssql/secrets/mssql.keytab sqluser

如果没有任何问题,应该会看到类似于以下示例的输出。 如果没有看到,跟踪将提供应查看的步骤的上下文。

3791545 1640722276.100275: Getting initial credentials for sqluser@CONTOSO.COM
3791545 1640722276.100276: Looked up etypes in keytab: aes256-cts, aes128-cts
3791545 1640722276.100278: Sending unauthenticated request
3791545 1640722276.100279: Sending request (202 bytes) to CONTOSO.COM
3791545 1640722276.100280: Initiating TCP connection to stream 10.0.0.4:88
3791545 1640722276.100281: Sending TCP request to stream 10.0.0.4:88
3791545 1640722276.100282: Received answer (185 bytes) from stream 10.0.0.4:88
3791545 1640722276.100283: Terminating TCP connection to stream 10.0.0.4:88
3791545 1640722276.100284: Response was from master KDC
3791545 1640722276.100285: Received error from KDC: -1765328359/Additional pre-authentication required
3791545 1640722276.100288: Preauthenticating using KDC method data
3791545 1640722276.100289: Processing preauth types: PA-PK-AS-REQ (16), PA-PK-AS-REP_OLD (15), PA-ETYPE-INFO2 (19), PA-ENC-TIMESTAMP (2)
3791545 1640722276.100290: Selected etype info: etype aes256-cts, salt "CONTOSO.COMsqluser", params ""
3791545 1640722276.100291: Retrieving sqluser@CONTOSO.COM from /var/opt/mssql/secrets/mssql.keytab (vno 0, enctype aes256-cts) with result: 0/Success
3791545 1640722276.100292: AS key obtained for encrypted timestamp: aes256-cts/E84B
3791545 1640722276.100294: Encrypted timestamp (for 1640722276.700930): plain 301AA011180F32303231313XXXXXXXXXXXXXXXXXXXXXXXXXXXXX, encrypted 333109B95898D1B4FC1837DAE3E4CBD33AF8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3791545 1640722276.100295: Preauth module encrypted_timestamp (2) (real) returned: 0/Success
3791545 1640722276.100296: Produced preauth for next request: PA-ENC-TIMESTAMP (2)
3791545 1640722276.100297: Sending request (282 bytes) to CONTOSO.COM
3791545 1640722276.100298: Initiating TCP connection to stream 10.0.0.4:88
3791545 1640722276.100299: Sending TCP request to stream 10.0.0.4:88
3791545 1640722276.100300: Received answer (1604 bytes) from stream 10.0.0.4:88
3791545 1640722276.100301: Terminating TCP connection to stream 10.0.0.4:88
3791545 1640722276.100302: Response was from master KDC
3791545 1640722276.100303: Processing preauth types: PA-ETYPE-INFO2 (19)
3791545 1640722276.100304: Selected etype info: etype aes256-cts, salt "CONTOSO.COMsqluser", params ""
3791545 1640722276.100305: Produced preauth for next request: (empty)
3791545 1640722276.100306: AS key determined by preauth: aes256-cts/E84B
3791545 1640722276.100307: Decrypted AS reply; session key is: aes256-cts/05C0
3791545 1640722276.100308: FAST negotiation: unavailable
3791545 1640722276.100309: Initializing KCM:0:37337 with default princ sqluser@CONTOSO.COM
3791545 1640722276.100310: Storing sqluser@CONTOSO.COM -> krbtgt/CONTOSO.COM@CONTOSO.COM in KCM:0:37337
3791545 1640722276.100311: Storing config in KCM:0:37337 for krbtgt/CONTOSO.COM@CONTOSO.COM: pa_type: 2
3791545 1640722276.100312: Storing sqluser@CONTOSO.COM -> krb5_ccache_conf_data/pa_type/krbtgt/CONTOSO.COM@CONTOSO.COM@X-CACHECONF: in KCM:0:37337

$ sudo klist
Ticket cache: KCM:0:37337
Default principal: sqluser@CONTOSO.COM
Valid starting Expires Service principal
12/28/2021 20:11:16 12/29/2021 06:11:16 krbtgt/CONTOSO.COM@CONTOSO.COM
renew until 01/04/2022 20:11:16

启用 Kerberos 和基于安全性的 PAL 日志记录

可以启用 security.kerberossecurity.ldap 日志记录,以标识 PAL(平台抽象层)中的特定错误消息。 使用下面 /var/opt/mssql/ 处的内容创建一个 logger.ini 文件,重启 SQL Server,然后重现失败。 PAL 的 Active Directory 错误和调试消息将记录到 /var/opt/mssql/log/security.log

[Output:security]
Type = File
Filename = /var/opt/mssql/log/security.log
[Logger]
Level = Silent
[Logger:security.kerberos]
Level = Debug
Outputs = security
[Logger:security.ldap]
Level = debug
Outputs = security

无需重启 SQL Server 就可以从 logger.ini 中选取记录器更改,但在 Active Directory 服务初始化期间或 SQL Server 启动期间启动可能会发生失败,在其他情况下则不会让人注意到。 重启 SQL Server 可确保捕获所有错误消息。

安全日志将继续写入驱动器,直到你删除 logger.ini 中的更改。 确定并解决问题后,记得禁用 security.kerberossecurity.ldap 日志记录,以防止驱动器空间不足。

PAL 记录器生成以下格式的日志文件:

<DATETIME> <Log level> [<logger>] <<process/thread identifier>> <message>

例如,下面是日志中的一个示例行:

12/28/2021 13:56:31.609453055 Error [security.kerberos] <0003753757/0x00000324> Request ticket server MSSQLSvc/sql.contoso.com:1433@CONTOSO.COM kvno 3 enctype aes256-cts found in keytab but cannot decrypt ticket

启用 PAL 日志记录并重现问题后,查找日志级别为 Error 的第一条消息,然后使用下表查找错误,按照指导和建议进行故障排除并解决问题。

常见错误消息

错误消息:“登录失败。 登录行为来自不受信任的域,不能用于集成身份验证。”

可能的原因

配置 Active Directory 身份验证后,尝试使用 Active Directory 帐户登录时会遇到此错误。

指南

这是一个一般性错误消息,必须启用 PAL 日志记录才能确定具体的错误消息。

可以参考此常见错误列表来确定每个错误的可能原因,然后按照故障排除指南来解决问题。

错误消息
找不到 Windows NT 用户或组 'CONTOSO\user'
由于存在错误,无法查找短域名
由于存在错误,无法对主机“<主机名>”执行 rDNS 查找
rDNS 查找未返回 FQDN
无法绑定到 LDAP 服务器
找不到密钥表条目
找不到“<主体>”的密钥表条目
在密钥表中找不到请求票证服务器“<主体>”(票证 kvno <KVNO>)
在密钥表中找到了请求票证服务器“<主体>”kvno <KVNO> 但 enctype 不是“<加密类型>”
在密钥表中找到了请求票证服务器“<principal>”kvno <> enctype“<加密类型>”,但无法解密票证

错误消息:找不到 Windows NT 用户或组 'CONTOSO\user'

可能的原因

在尝试创建 Windows 登录名时或者在组刷新期间可能会遇到此错误。

指南

若要验证问题,请遵循“登录失败。 登录行为来自不受信任的域,不能用于集成身份验证。 (Microsoft SQL Server,错误:18452)”中所述的指导“启用 PAL 日志记录”以确定具体错误,并相应地进行故障排除。

错误消息:“由于存在错误,无法查找短域名”

可能的原因

用于创建 Active Directory 登录名的 Transact-SQL 语法为:

CREATE LOGIN [CONTOSO\user] FROM WINDOWS;

命令中需要 NetBIOS 名称 (CONTOSO),但在后端执行 LDAP 连接时,必须提供域 (contoso.com) 的 FQDN。 若要执行此转换,请对 CONTOSO 执行 DNS 查找以解析为域控制器的 IP,然后可以绑定到该域控制器进行 LDAP 查询。

指南

错误消息“由于存在错误,无法查找短域名”表示 contosonslookup 无法解析为域控制器的 IP 地址。 应查看 DNS 查找和反向 DNS 查找,以确认 NetBIOS 和域名的 nslookup 匹配。

错误消息:“由于存在错误,无法对主机“<主机名>”执行 rDNS 查找”或 “rDNS 查找未返回 FQDN”

可能的原因

此错误消息主要表示所有域控制器都没有反向 DNS 记录 (PTR)。

指南

查看 DNS 查找和反向 DNS 查找。 在确定没有 rDNS 条目的域控制器后,有两个选项:

  • 添加所有域控制器的 rDNS 条目

    这不是一项 SQL Server 设置,必须在域级别进行配置。 可能需要与域管理团队合作,为对域名运行 nslookup 时返回的所有域控制器创建所需的 PTR 记录。

  • 将 SQL Server 限制到一部分域控制器

    如果无法为返回的所有域控制器添加 PTR 记录,可以将 SQL Server 限制到一部分域控制器

错误消息:“无法绑定到 LDAP 服务器 ldap://CONTOSO.COM:3268:本地错误”

可能的原因

这是 OpenLDAP 中的一般性错误,但通常表示以下两种情况之一:

  • 无凭据
  • rDNS 问题

下面是此类错误消息的一个示例:

12/09/2021 14:32:11.319933684 Error [security.ldap] <0000000142/0x000001c0> Failed to bind to LDAP server ldap://[CONTOSO.COM:3268]: Local error

指南

  • 无凭据

    如果无法为 LDAP 连接加载凭据,将首先引发其他错误消息。 应启用 PAL 日志记录,检查错误日志中此错误消息之前是否还有其他错误消息。 如果没有任何其他错误,则很可能不是凭据问题。 如果有,则解决你所看到的错误消息。 大多数情况下,会出现本文中所述的错误消息之一。

  • rDNS 问题

    查看 DNS 查找和反向 DNS 查找

    当 OpenLDAP 库连接到域控制器时,将提供域 FQDN (contoso.com) 或 DC 的 FQDN (kdc1.contoso.com)。 建立连接后(但在向调用方返回成功之前),OpenLDAP 库会检查它所连接到的服务器的 IP。 然后,它将执行反向 DNS 查找并检查所连接到的服务器的名称 (kdc1.contoso.com) 是否与请求的连接的域 (contoso.com) 相匹配。 如果不匹配,则作为一项安全功能,OpenLDAP 库会使连接失败。 这是 rDNS 设置在 Linux 上对于 SQL Server 非常重要原因之一,在此文档中进行了重点介绍。

错误消息:“找不到密钥表条目”

可能的原因

此错误表示密钥表文件存在访问问题,或者密钥表中没有包含所有必需条目。

指南

请确保密钥表文件具有正确的访问级别和权限。 密钥表文件的默认位置和名称是 /var/opt/mssql/secrets/mssql.keytab。 若要查看机密文件夹下所有文件的当前权限,可以运行以下命令:

sudo ls -lrt /var/opt/mssql/secrets

可以使用以下命令在密钥表文件上设置权限和访问级别:

sudo chown mssql /var/opt/mssql/secrets/mssql.keytab
sudo chmod 440 /var/opt/mssql/secrets/mssql.keytab

有关列出密钥表条目并设置正确权限的详细信息,请参阅上面的检查密钥表文件和权限部分。 如果未满足此部分中的任何条件,你将看到此错误或等效错误:"Key table entry not found"

错误消息:“找不到‘<主体>的任何密钥表条目”

可能的原因

尝试从密钥表检索 <principal> 的凭据时,找不到适用的条目。

指南

按照本文档中的检查密钥表文件和权限部分列出密钥表中的所有条目。 确保 <principal> 存在。 在这种情况下,主体帐户通常是 SPN 注册到的 network.privilegedadaccount。 如果不是,请使用 adutil 命令进行添加。 有关详细信息,请参阅使用 adutil 为 Linux 上的 SQL Server 配置 Active Directory 身份验证

错误消息:“在密钥表中找不到请求票证服务器‘<主体>(票证 kvno <>)”

可能的原因

此错误表示 SQL Server 找不到具有指定 KVNO(密钥版本号)的请求票证的密钥表条目。

指南

按照本文档中的检查密钥表文件和权限部分列出密钥表中的所有条目。 如果找不到与 <principal> 和 KVNO 匹配的错误消息,请使用该部分所述的步骤通过更新密钥表文件来添加此条目。

还可以运行以下命令以从 DC 获取最新 KVNO。 在运行此命令之前,需要先使用 kinit 命令获取或续订 Kerberos TGT。 有关详细信息,请参阅使用 adutil 为 SQL Server 创建 Active Directory 用户并设置服务主体名称 (SPN)

kvno MSSQLSvc/<hostname>

错误消息:“在密钥表中找到了请求票证服务器<主体> kvno <KVNO> 但 enctype 不是<加密类型>”

可能的原因

此错误表示客户端请求的加密类型在 SQL Server 的密钥表中不存在。

指南

若要验证,请按照本文档中的检查密钥表文件和权限部分列出密钥表中的所有条目。 如果找不到与主体、KVNO 和加密类型匹配的错误消息,请使用该部分所述的步骤通过更新密钥表文件来添加此条目。

错误消息:“在密钥表中找到了请求票证服务器 <主体> kvno <KVNO> enctype <加密类型>,但无法解密票证”

可能的原因

此错误表示 SQL Server 无法使用密钥表文件中的凭据来解密传入的身份验证请求。 此错误通常是由于密码不正确所致。

指南

使用正确的密码重新创建密钥表。 如果使用 adutil,请按照使用 adutil 为 Linux 上的 SQL Server 配置 Active Directory 身份验证中的步骤使用正确密码创建密钥表。

常用端口

此表显示了 Linux 上的 SQL Server 用于配置和管理 Active Directory 身份验证的常用端口。

Active Directory 服务 端口
DNS 53
LDAP 389
LDAPS 636
Kerberos 88