VPN 连上了,SQL Server 却拒绝 Windows 身份验证
VPN 登录成功,SQL Server 却拒绝 Windows 身份验证:先比对隧道账号与客户端令牌,再到服务器上读取 auth_scheme。
隧道建立起来了,服务器也能响应 ping,但数据库登录仍然因身份验证错误而失败。这种组合在 VPN 链路上很常见,却很少说明网络坏了,因为“监听端口可达”和“登录被接受”是两个不同的结果。让网关满意的那个身份,不一定是数据库客户端出示的身份。弄清究竟是哪个账号到达,就是这项工作的全部。
症状:服务器可达,登录被拒
超时说明数据包根本没到监听端口。身份验证错误说明监听端口应答了,并拒绝了凭据。这两条消息会把你送到不同的团队,混为一谈就会在从未成为问题的防火墙规则上浪费一天。
当错误是登录失败时,就别再盯着端口了。剩下的问题是:客户端出示了哪个 Windows 身份,服务器是否接受该身份,以及它是否被解析为有权限的数据库用户。
两个身份,一条隧道
VPN 账号在网关上完成身份验证,在多数部署里到此为止。数据库客户端则另外出示一个 Windows 令牌,取自运行它的进程;如果连接字符串要求,也可以出示 SQL 登录。网关上的本地 VPN 用户与承载 SQL Server 的域毫无关系,隧道也不会建立这种关系。
把个人机器连上 VPN 同样不会让它加入域。给本地账号改名、把密码改成和域用户一致,并不是入域流程,它产生的令牌不会被域控制器当作那个用户接受。
某些原生 Windows 远程访问客户端在配置文件如此设置时,可以把 VPN 凭据复用于网络资源。这种行为属于特定客户端和特定配置文件,而不是 VPN 连接的普遍性质,所以要针对正在使用的客户端去核实,而不是想当然。
读取客户端请求的模式
连接字符串决定客户端走哪条身份验证路径。集成安全性使用 Windows 令牌;用户名加密码的组合则选择 SQL 登录。它们是服务器配置里两种不同的模式,针对一次具体连接尝试只能启用其中一种。
Server=tcp:sql.lab.example,1433;Database=ops;Integrated Security=SSPI;Encrypt=True;TrustServerCertificate=False;
因为 Windows 登录失败就改用 SQL 登录,是一种把身份问题藏起来的变通做法,而且通常还得新建登录名和密码。如果部署要求 Windows 身份验证,就保留该模式并修好身份路径。SQL 登录也需要自己的权限,所以这个变通只是多买了一个要维护的账号。
还要确认是哪个应用程序在连接。以系统账号运行的服务、计划任务和交互式查询窗口,在同一台机器上可能出示三个不同的令牌,只有最后一个才与用户运行 whoami 时看到的一致。
问问服务器到底看到了什么
服务器能告诉你它解析出了哪个登录,以及连接是如何通过验证的。要在被调查的那个会话内部执行查询,因为管理员另开一次成功连接,并不能证明失败客户端的情况。
SELECT ORIGINAL_LOGIN() AS original_login,
SUSER_SNAME() AS current_context;
SELECT auth_scheme, net_transport
FROM sys.dm_exec_connections
WHERE session_id = @@SPID;
第一行区分了打开会话的登录与当前生效的安全上下文,在模拟身份的情况下这两者并不相同。第二行给出了身份验证方案,于是 KERBEROS、NTLM 和 SQL 就成了看得见的事实,而不是猜测。在你期待 Kerberos 的地方报出 NTLM 的连接,是名称解析或 SPN 的问题,不是密码问题。
错误号能进一步缩小范围。状态 5 通常意味着登录名根本没被解析,状态 8 通常意味着密码不匹配,状态 11 意味着凭据被接受了,但访问服务器失败。向管理员要状态号,而不是整条消息,因为消息本身是刻意含糊的。
| What you observe | What it suggests |
|---|---|
| Timeout, no listener | Route, firewall or wrong port |
| Login failed, state 5 | Name not resolved in the domain |
| Login failed, state 11 | Authenticated but no server access |
| Connected as NTLM | Target name or SPN mismatch |
当身份到了,Kerberos 仍然失败时
如果服务器看到的是预期的 Windows 身份,而集成身份验证仍然失败,问题就出在交换本身。Kerberos 需要为 SQL 服务账号注册的服务主体名称,以及一个用与之匹配的名称请求该服务的客户端。用 IP 地址连接无法匹配基于名称的 SPN,别名也只有同样注册过才能匹配。先检查客户端键入的名称,因为“用主机名能通、用 IP 不通”的连接,描述的正是这个问题。
请管理员复核已注册的身份和服务账号,而不是靠反复试验去创建重复的 SPN。重复注册会产生间歇性故障,比原来的问题更难诊断。
身份验证通了之后,登录仍然需要数据库用户和权限。VPN 登录成功、Windows 登录成功、以及能读取某张表的权限,是三个彼此独立的结果,在关闭工单之前每一项都值得单独核实。