存储 频道

存储课堂:NAS存储系统相关协议之CIFS

  【IT168 技术】 有些东西我们每天都在接触,却很少感受到它的存在。比如很多Windows用户天天使用文件共享,却不了解访问时所涉及的CIFS协议。本文要介绍的,就是这个协议的底细。

  在用户输入“\\服务器名\共享名”之后,首先被处理的是“服务器名”部分。无论这个服务器名是DNS还是NetBIOS的形式,都会被相应的协议解析成IP地址。得到IP地址后,客户端就向服务器发送第一个CIFS请求:“Negotiate Protocol Request”。这个请求包含了客户端所支持的各种CIFS版本(Dialect)。下图显示了客户端“10.32.106.116”向服务器“10.32.106.59”所发送的请求.

存储课堂:NAS存储系统相关协议之CIFS

  服务器收到该请求后,选择一个它支持的最新版本(比如NT LM 0.12),再通过“Negotiate Protocol Response”回复给客户端。上图显示的CIFS包是在Windows 2003抓的,所以我们看到的版本都属于SMB v1(SMB是CIFS的另一个名字)。如果这台客户端是Vista或者Windows 2008,我们还能看到SMB 2.x的选项。但是最终是否使用SMB2,还取决于服务器是否支持。

  Negotiate结束之后,客户端请求和服务器建立一个session。这个过程涉及的内容很多,所以大多数CIFS访问出错就发生在这里。

  1、在客户端发送的Session Setup Request里,包含了身份验证请求(如Kerberos的AP_REQ)。在服务器回复的Session Setup Reponse里,包含了验证结果(如Kerberos的AP_REP)。关于认证协议Kerberos和NTLM,我们再另文介绍。客户端使用NTLM还是Kerberos,取决于连接时输入的是IP,还是DNS/NetBIOS名。

存储课堂:NAS存储系统相关协议之CIFS

  2、Session Setup Request里,包含了客户端支持的各种特性,比如是否支持Unicode,SMB Signing等等。服务器也会在Session Setup Reponse里声明它所支持的特性。当双方支持的特性有冲突时,客户端可能会决定放弃连接。比如SMB Signing在Windows XP中被设成required,在服务器上被设成disabled时,Windows XP的某些版本会中断连接。

  3、在Session Setup Response里,服务器还会给用户分配一个UID。如果服务器出于某种原因无法产生该ID,这个连接也会失败。

  Session Setup如果通过,客户端就成功的连上了服务器。接下来,就是访问“\\服务器名\共享名”中的“共享名”部分了。这个操作在CIFS协议中由Tree Connect来完成。客户端发送的Tree Connect Request中指定了路径(在这里就是共享名),服务器在检查过用户对该路径的权限后,回复Tree Connect Response。检查用户权限是这样进行的:服务器从Session Setup Request中已经得到用户所属的组,再通过和该路径上的ACL对比,即可得到用户权限。有时候会出现奇妙的现象:如果通过IP地址访问服务器,有权限打开共享;如果通过DNS名访问服务器,则没有权限。这是因为用户在登陆客户端之后,才被加入到一个有权限访问该共享的组。由于Kerberos里包含组信息的ticket是在登陆时生成的,而NTLM是每次访问获得一次组信息的,所以才得到不同结果。解决方式是让用户再登陆一次,获得了新的ticket之后就没问题了。

  进了共享文件夹,用户尝试打开一个文件。客户端先通过Create命令从服务器得到该文件的FID,然后再利用Read命令读该FID的内容。每次读的大小有限制,默认是32KB。如果文件大小超过这个值,就得分多次读完。比如一个48KB的文件,第一次读可能是32KB,第二次读剩下的16KB。这其实不是一种高效的工作方式,就像一个人想吃肯德基的汉堡+鸡翅,他先叫了汉堡外卖,等送达后再叫鸡翅外卖。正确的方式应该是两个外卖一起叫。CIFS的确实施了AndX机制来实现多个请求一起发送,但是我在SMB v1的抓包中并没有看到这种现象。据说在SMB2上会工作得比较好。其实这个AndX机制还能减少网络丢包对性能的影响,我们将在分析NAS性能的文章中详细介绍。

存储课堂:NAS存储系统相关协议之CIFS

  本文所涉及的,只是CIFS协议的一小部分,但可以说是最重要的部分。由于时间有限,不能全面详细的介绍。有兴趣进一步研究的朋友,建议用WireShark抓几个CIFS包辅助学习。维基的SMB条目包含了很多参考资料,也是一个学习的好去处: http://en.wikipedia.org/wiki/Server_Message_Block

0
相关文章