SQL Kerberos的原理及实验

参考文献

Microsoft SQL Server企业级平台管理实践

Kerberos Explained

Kerberos (protocol)wiki

正文

这一周一直在研究kerberos的原理,并做了一些实验,现在做一下总结。

首先我们要知道,SQL Server中的验证机制。SQL Server有两种验证机制,一种是windows验证,还有一种是SQL Server验证,这也就对应了两种用户类型,即SQL Server自己的用户账号和Windows用户账号。

对于SQL Server账号,SQL Server会对用户发过来的用户名与密码进行核对(比如我们安装数据库是自动创建的sa账号就是sql server账号)。只要正确,认证就可以通过。这个过程比较简单,一般不会出问题。

对于Windows账号,SQL Server需要借助Windows来帮助完成认证过程。如果这个认证过程出现问题,则SQL Server会出错。Windows用户认证机制比SQL Server认证要复杂得多,不但牵涉SQL Server服务器和客户端,还要牵涉域服务器。我们在安装SQL Server的时候要求我们添加windows账户,我们一般添加的都是当前的本机账户。

SQL Server内部,对SQL Server账号和Windows账号的处理有所不同。对Windows账号,SQL Server依赖于Windows做身份认证,自己无须保存和维护用户密码信息。对SQL Server账号,SQL Server自己负责用户认证工作,所以需要自己来保存和维护用户密码。像Windows一样,SQL Server只保存密码经过加密算法以后的hash值,而不保存密码的原文。所以管理员可以直接修改密码,但是无法知道密码的原文是什么。

Windows认证是一个相对复杂的机制,它至少需要三方的参与:SQL Server、客户端和域控制器(Domain Controller),因此在后面的实验中会创建三台虚拟机,分别担任DC,Client和ServerWindows认证技术有两种,NTLMKerberos。这两种方法都能够完成用户认证。使用哪一种方法不是客户端应用指定的,也不是SQL Server自己决定的。在SQL Server客户端申请用户认证的时候,会去调用Windows认证API,根据当时Windows API返回值决定使用哪种方法。

接下我们直接进入主题,讲讲kerberos是如何验证的。我们可以参考Kerberos Explained 中的kerberos连接原理图,如下图所示:

从上面可以看出,kerberos连接一共有六步,我分别介绍这六步主要做了哪些工作。

  1. 当客户端登录的时候,会将自己的用户名发送给KDC中的Authentication Service(AS),并申请一个TGT,一般情况下KDC是在Domain Controller(DC)上面的。
  2. 如前面提到的,DC中不保存用户明文密码的,只保存了密码的hash值,所以AS将该用户的TGT用其密码hash值进行加密,并将这个加密后的TGT传送给客户端。客户端可以使用自己的密码hash解密得到TGT,如果密码hash错误将得不到TGT。所以AS的作用是保证客户端的用户不是假冒的。
  3. 当客户端申请链接网络中的服务时(可以有很多类型的服务,比如SQL Server,Sharepoint等),客户端将自己的TGT,要访问服务的Server Principal Name(SPN)发送给TGS,申请用于访问服务的Service Ticket。
  4. TGS验证是否只有一个服务账户注册过这个SPN,如果是的话,那么就将这个SPN用服务账户的信息进行加密,然后将这个Service Ticket返回给客户端。
  5. 客户端将要访问服务的Service Ticket发送给服务端,如果服务端能够用自己的账户名正确解密Serice Ticket,那么就建立连接,所以从这里我们看到,TGS是为了保证服务器端不是假冒的,避免用户登录钓鱼网站。
  6. 服务器端发送session 给客户端,表明建立连接

以上就我我对kerberos连接的理解。

PS:2012-8-17

上面对于kerberos连接的理解过于简单,可以参考:

How the Kerberos Version 5 Authentication Protocol Works: Logon and Authentication

还可以参考我的另外一篇博客:Kerberos连接过程

SQL Server中配置Kerberos

SQL Server在每次启动的时候,都会去尝试用自己的启动账号注册SPN。但是在Windows域里,默认普通机器账号有权注册SPN,但是普通域用户账号是没有权利注册SPN的。这就会导致这样一个现象,SQL Server如果使用“Local System account”来启动,Kerberos就能够成功,因为SQL Server这时可以在DC上注册SPN。如果用一个域用户来启动,Kerberos就不能成功,因为这时SPN注册不上去。

解决的方法之一,当然可以使用工具SetSPN -S来手动注册SPN。但是这不是一个最好的方法,毕竟手工注册不是长久之计。如果SPN下次丢了,又要再次手动注册。所以比较好的方法,是让SQL Server当前的启动账号有注册SPN的权力。要在DC上为域账号赋予“Read servicePrincipalName”和“Write serverPrincipalName”的权限即可。讲解如何配置kerberos。

步骤1

使用msft\sanzhang这个域账户启动Machine A,在Machine A中使用local system账户启动sql server服务,这样在服务启动的时候,就会自动注册spn。我们通过在SSMS中输入如下的存储过程:

sp_readerrorlog 0,1,'spn'

查看到

LogDate 

ProcessInfo 

Text

2012-08-10 00:09:22.980

Server 

The SQL Server Network Interface library successfully registered the Service Principal Name (SPN) [ MSSQLSvc/SANZ-W7.msft.com ] for the SQL Server service.

2012-08-10 00:09:22.980

Server

The SQL Server Network Interface library successfully registered the Service Principal Name (SPN) [ MSSQLSvc/SANZ-W7.msft.com:1433 ] for the SQL Server service.

步骤2

使用msft\wuwang域账户启动Machine B,并且同时使用这个域账户启动sql server服务。因为域账户没有权限注册SPN,所以在服务启动以后,查看errorlog,

sp_readerrorlog 0,1,'spn'

得到如下结果:

LogDate 

ProcessInfo 

Text

2012-08-10 00:08:57.890

Server 

The SQL Server Network Interface library could not register the Service Principal Name (SPN) for the SQL Server service. Error: 0x2098, state: 15. Failure to register an SPN may cause integrated authentication to fall back to NTLM instead of Kerberos. This is an informational message. Further action is only required if Kerberos authentication is required by authentication policies.

Troubleshooting可以参考The SQL Network Interface library was unable to register SPN

此时我们要为域账户添加注册spn的权限,具体方法如下:

在DC上运行工具“adsiedit.msc”,在“ADSI edit”里,展开“Domain”—“DC=XXXX,DC=XXX”(这里是域的名字)—“CN=Users”—“CN=wuwang”,打开这个用户的属性,按照如下图所示的操作添加“Read servicePrincipalName”和“Write serverPrincipalName”的权限。

假如machine B不使用域账户登录,就不用这么麻烦了。配置完上述权限以后,重启服务就可以看到自动注册SPN了。

步骤3

打开SSMS,在machine B中的sql server实例中添加login,记得是添加windows authentication的login,我们这里要添加的就是sanzhang这个账户。

之前我们一直思考kerberos如何控制账户访问呢,是不是域里面的所有账户都可以访问呢?这里就有答案了。只有被instance添加到windows authentication中的login用户才可以连接数据库,而具体访问数据库的权限还是在sql server里面配置的。

步骤4

在machine A上面使用sanzhang 这个域账户,连接 machine B上面的数据库实例,SSMS中的数据库连接字符串是Tcp:MACHINEB\,登录账户是msft\sanzhng。成功连接到machine B上面的数据库实例

步骤5

为了验证使用的是kerberos,可以使用如下查询:

SELECT auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@spid ;

查询结果如下图所示:

 

 

 

 

posted @ 2012-08-11 20:13  xwdreamer  阅读(2468)  评论(0编辑  收藏  举报