更新

更新

我正在尝试让我的 MSSQL 数据库用户能够 BULK INSERT / OPENROWSET() 存储在我们的 DFS/cifs/smb 网络共享上的 CSV 文件。

初始设置

我已将 MSSQL 服务设置为以域用户帐户运行,EXAMPLE\svc_mssql并将该用户添加到具有相关 DFS 共享的读取权限的安全组(例如\\example.org\myshare\data\path\to\mydata.csv)。这允许通过 SQL 身份验证连接到数据库的用户成功读取共享上的文件,因为不存在 Kerberos 双跳问题:

C:\Temp>sqlcmd -N -S %DB_HOSTNAME% -U %DB_USERNAME% -P %DB_PASSWORD%
1> SELECT
2>   CAST(CONNECTIONPROPERTY('auth_scheme') AS nvarchar(10)) AS auth_type,
3>   COUNT(*) AS NumLines
4> FROM OPENROWSET(
5>    BULK '\\example.org\myshare\data\path\to\mydata.csv'
6>  , FORMATFILE = '\\example.org\myshare\data\path\to\mydata.fmt'
7> ) AS f;
8> GO
auth_type  NumLines
---------- -----------
SQL                 73

(1 rows affected)

凯尔伯罗斯

我有手动注册 SPN对于 AD 中的 MSSQLSvc,它们确实在该服务帐户上正确显示:

C:\Temp>setspn -Q MSSQLSvc/DBSERVER.example.org
Checking domain DC=example,DC=org
CN=svc_mssql,OU=ServiceAccounts,DC=example,DC=org
        MSSQLSvc/DBSERVER.example.org
        MSSQLSvc/DBSERVER.example.org:1433

Existing SPN found!

这使得我能够使用 Kerberos 身份验证成功连接到 SQL Server:

C:\Temp>sqlcmd -N -S %DB_HOSTNAME% -E
1> SELECT CAST(CONNECTIONPROPERTY('auth_scheme') AS nvarchar(10)) AS auth_type;
2> GO
auth_type
----------
KERBEROS

(1 rows affected)

无约束委派

如果我将服务帐户设置为受信任的委派(即不受约束的委派),如下所示:

PS C:\Temp> Get-ADUser svc_mssql -Properties TrustedForDelegation,TrustedToAuthForDelegation `
>>   | Select-Object Name,TrustedForDelegation,TrustedToAuthForDelegation

Name      TrustedForDelegation TrustedToAuthForDelegation
----      -------------------- --------------------------
svc_mssql                 True                      False

然后一切都运行正常:

C:\Temp>sqlcmd -N -S %DB_HOSTNAME% -E
1> SELECT
2>   CAST(CONNECTIONPROPERTY('auth_scheme') AS nvarchar(10)) AS auth_type,
3>   COUNT(*) AS NumLines
4> FROM OPENROWSET(
5>    BULK '\\example.org\myshare\data\path\to\mydata.csv'
6>  , FORMATFILE = '\\example.org\myshare\data\path\to\mydata.fmt'
7> ) AS f;
8> GO
auth_type  NumLines
---------- -----------
KERBEROS            73

(1 rows affected)

数据包追踪 - 无约束委派

经过多次尝试和错误,并试图推测/猜测约束委派需要什么之后,我在数据库服务器上安装了 wireshark,并从正在运行的无约束设置中抓取了数据包跟踪。我不是网络专家,但这是我在该跟踪中看到的内容(我认为):

  1. TGS-REQ/REP 用于cifs/DOMAINCONTROLLER01.example.org
  2. TGS-REQ/REP 用于krbtgt/EXAMPLE.ORG
  3. SMB 树连接请求\\DOMAINCONTROLLER01.example.org\IPC$
  4. SMB Ioctl FSCTL_DFS_GET_REFERRALS\example.org\myshare
  5. TGS-REQ/REP 用于cifs/FILESERVER01
  6. SMB 树连接请求\\FILESERVER01\IPC$
  7. SMB Ioctl FSCTL_DFS_GET_REFERRALS\FILESERVER01\myshare
  8. TGS-REQ/REP 用于cifs/FILESERVER02
  9. SMB 树连接请求\\FILESERVER02\IPC$
  10. SMB Ioctl FSCTL_DFS_GET_REFERRALS\FILESERVER01\myshare\data
  11. TGS-REQ/REP 用于cifs/NASCLUSTER01
  12. SMB 树连接请求\\NASCLUSTER01\Data
  13. 更多 SMB 流量实际上读取文件......

我可以看到需要代理/模拟这两个cifs/FILESERVERSPN,因为它们是 DFS 命名空间的底层节点。经过一番研究,我也能理解 SPN cifs/NASCLUSTER,因为那是文件服务器实际存储数据的地方。

不过,前两个请求我不太理解。我猜第一个请求cifs/DOMAINCONTROLLER01.example.org是为了让 SQL Server 能够查找托管所请求文件共享的 DFS 命名空间中的节点。如果是这样,我想我需要允许服务帐户在所有域控制器上进行委托cifs,对吗?

剩下的就是krbtgt/EXAMPLE.ORG。我不明白这是做什么的。为什么会得到 TGT?我是不是误读了跟踪?我看到它是一个 tgs-req,其 msg-type 为krb-tgs-req (12)-- 与其他相同。这是协议转换吗?如果是,为什么在这种情况下会发生这种情况?

更新

svc_mssql因此,我(再次)尝试为以下 SPN设置约束委派:

  1. cifs/FILESERVER01
  2. cifs/FILESERVER02
  3. cifs/NASCLUSTER
  4. cifs/DOMAINCONTROLLER01

查看数据包跟踪,我发现的数据包为 ,krb-tgs-req (12)错误代码为。原始数据包为= ,wireshark 将其解码为:cifs/FILESERVER01krb-error (30)eRR-BADOPTION (13)krb-tgs-reqkdc-options40830000

kdc-options: 40830000
    0... .... = reserved: False
    .1.. .... = forwardable: True
    ..0. .... = forwarded: False
    ...0 .... = proxiable: False
    .... 0... = proxy: False
    .... .0.. = allow-postdate: False
    .... ..0. = postdated: False
    .... ...0 = unused7: False
    1... .... = renewable: True
    .0.. .... = unused9: False
    ..0. .... = unused10: False
    ...0 .... = opt-hardware-auth: False
    .... 0... = unused12: False
    .... .0.. = unused13: False
    .... ..1. = constrained-delegation: True
    .... ...1 = canonicalize: True
    0... .... = request-anonymous: False
    .0.. .... = unused17: False
    ..0. .... = unused18: False
    ...0 .... = unused19: False
    .... 0... = unused20: False
    .... .0.. = unused21: False
    .... ..0. = unused22: False
    .... ...0 = unused23: False
    0... .... = unused24: False
    .0.. .... = unused25: False
    ..0. .... = disable-transited-check: False
    ...0 .... = renewable-ok: False
    .... 0... = enc-tkt-in-skey: False
    .... .0.. = unused29: False
    .... ..0. = renew: False
    .... ...0 = validate: False

我将这些选项与无约束委派中的数据包进行了比较,唯一的区别是位constrained-delegation被翻转了——正如预期的那样。我做错了什么?

帮助!?!?!?

答案1

因此,事实证明,在我们最初的故障排除过程中,我们DBSERVER$在 AD 中为计算机帐户启用了 Kerberos 委派。这显然导致系统走上了寻找 RBCD 的不同路径,而我们并没有这样做。

最重要的是,将机器帐户重置为无委派,并在两个文件服务器和 NAS 集群的服务帐户上添加约束委派,彻底解决了该问题。

相关内容