SMB2协议特性之oplock与lease(下)
Posted 刘爱贵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SMB2协议特性之oplock与lease(下)相关的知识,希望对你有一定的参考价值。
前期回顾
上篇文章我们介绍了oplock/lease的相关概念及其基本工作原理,由于间隔时间较长,忘记的读者可以先去回顾一下。本篇文章带大家了解一下,在实际场景中,oplock/lease是如何工作的。
实际场景分析
在一些警匪影视剧中,我们可能看到过这类场景,警方通过监听嫌疑人的电话,来获取有用信息,从而为警方的下一步行动提供依据。
类似地,我们可以通过网络抓包工具(如tcpdump,wireshark等)来“监听”SMB2协议的客户端与服务端的通信内容,然后对它们之间传递的控制信息加以分析,从而了解它们是如何工作的。
接下来分几个场景看看:
(1)单客户端场景
(2)多客户端场景
(3)oplock关闭场景
这里的每个场景都是独立的,它们之间互不干扰。
在上述场景中,客户端系统采用Windows 10(企业版),服务端系统采用CentOS 7.9,SMB2 协议服务端软件使用开源软件Samba。网络抓包工具使用tcpdump,分析网络数据包使用具有图形界面的wireshark。此外,为了区分只读类型和读写类型请求,我们以执行程序的方式来替代手动操作方式,客户端执行的Python程序代码如下(openfile.py):
(一)单客户端场景
→ 场景描述
单客户端依次以只读和读写方式打开SMB2共享目录下的同一个文件。
→ 操作步骤
在一个Windows 10系统上,挂载SMB2共享目录到本地Z盘,分别打开两个命令提示符,依次执行python openfile.py ro和python openfile.py rw命令,抓取该过程的网络通信数据包截图如下(已过滤掉无关的非SMB2数据包):
→ 数据包分析
首先对上图做下简单说明,整体一行代表一次SMB2请求或者响应,No.列代表网络数据包或数据帧编号,Source列是发送方地址,Destination列是接收方地址,Protocol列是协议版本,Info列是所执行操作的描述信息。
其中,客户端以只读方式打开文件时,发出的lease请求(作为SMB2 Create请求(即数据包4)的一部分,相当于子请求)的展开信息如下图:
其中Lease Key是客户端生成的唯一标识,用于表示lease的所有者。Lease State一行代表所请求的lease类型,可以看到,即使应用程序以只读方式打开文件,SMB2客户端协议也会请求最高类型的lease(即RWH lease)。对应的响应(数据包6)的展开信息如下图:
可以看到,服务端返回的也是最高类型的lease,这个比较好理解,因为当前只有一个进程访问这个文件,相当于独占这个文件。然后,客户端运行一个新进程以读写方式打开该文件时(注意此时之前的只读访问并未退出,而是处于睡眠中),lease请求的展开信息如下图,请求的同样是RWH lease:
该请求的响应信息展开如下图,可以看到,服务端返回的也是最高类型的lease。
总结一下,单客户端多次打开同一个文件,每次都会请求RWH lease,并且授予的也都是RWH lease,不论是以只读还是读写方式打开文件。
(二)多客户端场景
→ 场景描述
两个不同的客户端(比如A和B)依次对同一个SMB2共享目录下的同一个文件(如f1.txt)进行只读操作。
→ 操作步骤
在两个不同的Windows 10系统上,挂载同一个SMB2共享目录到各自本地Z盘,都打开一个命令提示符,依次执行python openfile.py ro命令,在服务端抓取该过程的网络通信数据包截图如下(已过滤掉无关的非SMB2数据包):
→ 数据包分析
首先,客户端A(172.26.57.51)的lease请求展开如下图:
可以看到,申请的是最高类型lease,对应的服务端响应如下:
此时没有其他客户端访问该文件,相当于单客户端场景,服务端返回最高类型lease,并赋予lease epoch(即版本号)为1。客户端B(172.26.57.53)的lease请求信息如下:
可以看到,同样也是申请的最高类型lease。但是下一个数据包却是Lease break notification(如下图),而不是lease响应,这是为什么呢?原因是有其他客户端访问了同一个文件,“打破”了当前客户端A对文件的“独占”状态(RWH lease相当于独占),而为了保证多客户端数据访问的一致性,服务端必须先通知客户端A,调整其当前lease类型。
然后,客户端A发送Lease break acknowledgment请求来确认新的lease类型:
服务端通过返回STATUS_PENDING来延缓回复客户端B的打开文件请求:
然后,服务端回复客户端A的acknowledgment请求,完成对lease break处理。
然后,服务端回复客户端B的打开文件请求,并授予相应lease类型(RH lease),如下图所示,最后客户端B开始读取文件和其他操作,不再赘述。
总结一下,多个客户端打开同一个文件,每个客户端申请的都是RWH lease,第一个lease申请会被授予RWH lease,之后会根据服务端的lease分配算法进行计算,最终为每个客户端会取得一个合适的lease类型。
(三)Lease关闭场景
如果服务端关闭了oplock,那么在协议协商阶段,客户端就可以知道该服务端不支持lease,如下图:
于是,当客户端创建或者打开文件时,服务端将不再授予任何oplock,理论上客户端不能缓存任何数据了,也就相当于关闭了客户端缓存,如下图所示。
以上场景还是相对比较简单,更多复杂的场景还需感兴趣的读者去继续研究。
协议实现讨论
Oplock/lease是一种客户端缓存机制,目的是为了提升性能,客户端缓存的具体策略和参数(如缓存大小,缓存过期时间等等)主要由SMB2协议客户端决定,然而SMB2客户端大多数运行在Windows系统上,Windows系统本身又是闭源的,我们可做的工作极其有限。
另一方面,SMB2协议采用的是C/S架构,为了提升协议性能,不仅可以优化协议客户端,也可以优化协议服务端。文中使用的SMB2服务端软件是开始于1992年的开源软件Samba,该项目是目前开源社区对SMB2协议支持最完整的并且是使用者最多的项目。
虽然Samba被广泛使用,但是以如今的存储发展趋势来看,新型高速介质的逐渐普及,新兴应用的不断涌现,都对存储服务提出了更高的要求。从这个角度来看,Samba作为SMB2协议的实现,其实算不上十分出色,笔者认为这是多方面原因造成的,如下图:
基于上述原因,并考虑到对于目前很多应用场景,标准文件协议(NFS和SMB)还是不可或缺的,可以预见,开发一个没有历史包袱的高效的SMB server几乎是势在必行。
展望
FAFS是大道云行自主研发的一款企业级全闪分布式文件存储产品,可提供基于标准协议的文件服务,以高性能和自主可控为主要设计目标,产品采用了开放式架构。
其中,作为FAFS的协议层之一,一个没有历史包袱的新的SMB server正在开发中。新的SMB server,同样以高性能和自主可控为目标,且与底层分布式存储紧密结合,并充分考虑新型高速介质的特性。
此外,笔者认为,SMB2协议涉及的内容还是比较多的,尤其是Windows系统本身是闭源的,想要去深入理解并实现SMB2协议,需要做的工作还很多很多,但尽管如此也要相信,“道阻且长,行则将至;行而不辍,未来可期”。
参考资料:
[1] [MS-SMB2].pdf
https://msdn.microsoft.com/en-us/library/cc246482(PROT.13).aspx
[2] 深入SMB2协议之oplock vs lease
https://www.jianshu.com/p/fc6cd66a7a43
以上是关于SMB2协议特性之oplock与lease(下)的主要内容,如果未能解决你的问题,请参考以下文章