SMB小传 —— SMB网络文件系统协议介绍

SMB网络文件系统协议, 全名服务器消息块(Server Message Block),曾用名CIFS(通用互联网文件系统 Common Internet File System), 公元1983年诞生于IBM[1],幼年得到英特尔和微软的照料,最终在微软的培养下成长为当今世上网络文件系统协议两极之一的存在。本文就来聊聊SMB的生平二三事。

一、未曾停下的演进

作为一个诞生在谷歌、亚马逊、雅虎、甚至思科都不曾存在的互联网“远古”时代[2]的网络协议,SMB的早期版本(SMB 1.0/CIFS,以下简称SMB1)在不停地修修补补中却也渐渐无法适应现代的网络环境了。如今的互联网已经不再简单不再纯粹,互联网上存储着海量的数据并还在快速生产新数据,运行着各式各样的网络应用,也同样充斥着的无处不在的恶意攻击。

SMB1协议有太多的缺点,除了近期在2017年因为WannaCry病毒事件而再次暴露出来的巨大安全漏洞之外,便是SMB1协议特性导致了其对于网络资源的巨大耗费以及在远距通信场景下极差的性能。SMB1显著的性能问题还使得CIFS加速器成为了WAN加速类产品[3]的必备组件,思科、riverbed等公司都研发过此类功能,当然这些都是题外话了。对于SMB1的种种不足和为什么要停止使用SMB1,微软SMB项目的负责人Ned Pyle已经有了清晰的诉说[4, 5],本文便不再赘述了。

下面(表-1),本文列表总结了SMB协议各个版本的发布时间以及各版本所带来的重要协议特性。可以看到,从1983年到2007年这整整24年中,SMB作为一个网络文件系统的基本功能已经比较完整了,各种文件系统操作、用户认证、消息签名、客户端缓存等等的功能都有,更是取消了对NetBIOS协议层的依赖从而直接使用445端口运行在TCP/IP之上。至于为何SMB在1996年一度改名为CIFS呢?那都是源于微软面对Sun公司的NFS(Network File System)协议面向Web服务的扩张(WebNFS),而进行的一次失败的IETF网络文件系统标准化尝试[6],对此本文不多作细说。不过这一次改名导致了人们现在有时也会以CIFS来称呼SMB协议,而在Linux平台的SMB客户端甚至一直保持了CIFS的命名。

随着互联网产业的快速发展,SMB堪忧的安全性和愈发跟不上时代的性能使得微软不得不对SMB协议进行大刀阔斧的修订,并在2007年发布了SMB 2.0。仔细观察就会发现,SMB 2.X和SMB 3.X带来的众多新特性基本都是是围绕着增加安全性和提升性能这两个主题来设计的。

SMB版本

年代

相应操作系统版本

重要协议特性

SMB 3.1.1

2015

Windows 10

Windows Server 2016

- 传输加密算法协商
- 预认证完整性检查(pre-authentication integrity)

SMB 3.0.2

2013

Windows 8.1

Windows Server 2012 R2

- 客户端直读直写请求
- SMB Direct(RDMA)性能改进

SMB 3.0

2012

Windows 8

Windows Server 2012

- 目录级元数据客户端缓存(directory lease)
- 持久句柄(persistent handle)
- 基于AES-CCM算法的数据传输加密
- 消息签名(message signing)改用AES-CMAC算法
- SMB Direct(RDMA)支持
- 多通道(multi-channel)

SMB 2.1

2009

Windows 7

Windows Server 2008 R2

- 基于Lease的文件数据客户端缓存
- 多协议版本支持协商(multi-protocol negotiate)
- 弹性句柄(resilient handle)

SMB 2.0.2

2008

Windows Vista SP1

Windows Server 2008

- SMB指令数量减至19个
- 基于信用点(credit)的流控机制
- 改进复合请求机制(request compounding)
- 耐用句柄(durable handle)
- 消息签名(message signing)改用SHA-256算法
- 支持软链接(symbolic link)
- 提升最大数据块尺寸(maximum block size)

SMB 2.0

2007

Windows Vista

======================== 时代的分割线 ========================

SMB 1.0/CIFS

2000

Windows 2000

- 包含100+指令的指令集
- 打开(open)、读(read)、修改(modify)、关闭(close)等文件操作
- 取消(cancel)操作
- 直接运行于TCP/IP协议之上(Direct hosting of SMB over TCP/IP)
- 查询、设定文件和卷属性(attributes)
- 基于NTLM、Kerbeors等协议的用户认证
- 基于MD5算法的消息签名(message signing)
- 基于机会锁(opportunistic lock / oplock)的文件数据客户端缓存

CIFS

1996

Windows NT 4.0

早期SMB

1983

MS-DOS

OS/2

表-1 SMB协议版本历史与重要特性[7]

然而,如果用户们想要真正用上新版SMB协议带来的新特性,就必须保证SMB客户端和SMB服务端都能够支持带有该特性的协议版本。更因为微软并不支持向旧版Windows系统移植新版的SMB客户端或服务端程序,用户只能更新操作系统之后才能够体验更新的SMB特性。在表-2中,我们列出了不同Windows系统组合之间所能够支持的最高的SMB版本以供参考。

Windows版本
Windows 10
WS 2016
Windows 8.1
WS 2012 R2
Windows 8
WS 2012
Windows 7
WS 2008 R2
Windows Vista
WS 2008
更早版本
Windows 10
WS 2016
SMB 3.1.1
SMB 3.0.2
SMB 3.0
SMB 2.1
SMB 2.0.2
SMB 1
Windows 8.1
WS 2012 R2
SMB 3.0.2
SMB 3.0.2
SMB 3.0
SMB 2.1
SMB 2.0.2
SMB 1
Windows 8
WS 2012
SMB 3.0
SMB 3.0
SMB 3.0
SMB 2.1
SMB 2.0.2
SMB 1
Windows 7
WS 2008 R2
SMB 2.1
SMB 2.1
SMB 2.1
SMB 2.1
SMB 2.0.2
SMB 1
Windows Vista
WS 2008
SMB 2.0.2
SMB 2.0.2
SMB 2.0.2
SMB 2.0.2
SMB 2.0.2
SMB 1
更早版本
SMB 1
SMB 1
SMB 1
SMB 1
SMB 1
SMB 1

表-2 SMB协议版本历史与重要特性 (* WS = Windows Server)

二、一次完整的SMB会话

简单地聊完SMB的演进之后,本小节再来简述一下SMB的网络报文格式以及一个典型SMB会话的各个生命阶段。本节讲述关于SMB2和SMB3相关的协议内容,对于已经被摒弃的SMB1协议便略去不提了。

SMB报文格式

图-1详细展示了SMB2和SMB3的报文头部结构,对这些技术细节不感兴趣的读者可跳过本节。至于每个单独的SMB指令的报文格式便不在本文中展开了,有兴趣的读者可自行翻阅MS-SMB2协议文档。细心的读者可能会好奇,为什么SMB3没有独立的协议文档呢?一则SMB2和SMB3在报文格式上并没有太大差异,并不需要单独开一篇文档;二则,其实SMB 3.0在WIndows 8测试版阶段还是命名为SMB 2.2的,但微软工程师们经过再三考虑,认为以SMB3新增的代码之多、新特性之丰富,一个单独的主版本号才是理所应当的[8]。

SMB小传 —— SMB网络文件系统协议介绍

图-1 SMB报文格式

SMB会话的生命阶段

如图-2所示,一个普通的SMB会话从开始到结束一般会经过以下六个生命阶段:

1. SMB协议协商(Negotiate)
在一个SMB还没有开始的时候,由客户端率先发出一个协商请求。在请求中,客户端会列出所有它所支持协议版本以及所支持的一些特性(比如加密Encryption、持久句柄Persistent Handle、客户端缓存Leasing等等)。而服务端在回复中则会指定一个SMB版本且列出客户端与服务端共同支持的特性。
2. 建立SMB会话(Session Setup)
客户端选择一个服务端支持的协议来进行用户认证,可以选择的认证协议一般包括NTLM、Kerberos等。按照选择的认证协议的不同,这个阶段可能会进行一次或多次SESSION_SETOP请求/回复的网络包交换。至于NTLM或Kerberos认证协议的细节,我们会另文再叙。
3. 连接一个文件分享(Tree Connect)
在会话建立之后,客户端会发出连接文件分享的请求。源于文件系统的树形结构,该请求被命名为树连接(Tree Connect)。以SMB协议的阿里云NAS为例,一般的SMB挂载命令为:
net use z: \\XXX.nas.aliyuncs.com\myshare
其中的“ \\XXX.nas.aliyuncs.com\myshare”便是我们将要连接的那个文件分享,也便是那棵“树”。如果在“myshare”中创建有子目录“abc”,那直接连接“abc”这棵子树也是可以的:
net use z: \\XXX.nas.aliyuncs.com\myshare\abc
4. 文件系统操作
在文件分享连接成功之后,用户通过SMB客户端进行真正的对于目标文件分享的业务操作。这个阶段可以用到的指令有CREATE、CLOSE、FLUSH、READ、WRITE、SETINFO、GETINFO等等。
5. 断开文件分享连接(Tree Disconnect)
当一个SMB会话被闲置一定时间之后,Windows会自动断开文件分享连接并随后中止SMB会话。这个闲置时间可以通过Windows注册表进行设定[9]。当然,用户也可以主动发起断开连接请求。
6. 终止SMB会话(Logoff)
当客户端发出会话中止请求并得到服务端发回的中止成功的回复之后,这个SMB会话至此便正式结束了。

SMB小传 —— SMB网络文件系统协议介绍

图-2 SMB会话的六个阶段

三、现状与展望

聊过了SMB的过往历史和一小部分技术细节之后,本文再来说说关于SMB的一些其他的故事,也对SMB协议的未来做一个浅薄的展望。

与开源社区的恩怨情仇

虽然微软长久以来主导着SMB协议标准的订立与发展,是SMB协议的实质拥有者。不过我们无法忽视开源社区对SMB发展的贡献。最早发布于1992年的SAMBA则是开源界对SMB协议支持最完整也是使用者最多的项目。SAMBA是一个松散的开发者团队,开发SAMBA本身并不会获得收入或盈利,所以这个团队的成员大多还有另一份谋以生计的正职工作[10]。在2018年6的微软互操作研讨会上[11],笔者便有幸遇到几位SAMBA的开发者,他们中有SAMBA主要维护者,来自谷歌的Jeremy Allison和当时刚刚受聘于微软的Linux CIFS客户端开发者Steve French。表-3和表-4列出了历年来SAMBA对在Unix/Linux平台上支持SMB协议作出的努力和成绩。

现在的微软每年都会和开源社区的开发者们一起参加各种研讨会,有微软主办的互操作研讨会、全球网络存储工业协会(SNIA,Storage Networking Industry Association)举办的存储开发者大会等等。然而,早年的微软和开源社区之间的关系并没有现在这般和谐,甚至整个开源社区都曾将微软视为头号公敌。微软和SAMBA之间也曾一度在欧洲对簿公堂[12]。但这些都在2010前后发生了转变,微软逐渐确立了其云优先的公司路线,也逐渐以开放的心态来对待开源社区,时至今日,微软已经成为了全球最大的开源代码贡献者之一了[13]。从2011年起,微软便遵循GPL开源协议开始向SAMBA项目贡献代码[14]。甚至其最近还收购了全球最大的开源代码平台Github。

SAMBA版本
发布日期
SMB协议支持版本
4.3.0
2015年9月
SMB 3.1.1
4.1.0
2013年10月
SMB 3
3.6.0
2011年8月
SMB 2
3.5.0
2010年3月
SMB 2(实验性支持)

表-3 SAMBA对SMB协议的支持(SMB服务端)[15]

Linux内核版本
发布日期
Linux CIFS重要更新内容
4.17
2018年6月
支持SMB 3.1.1
4.13
2017年9月
默认SMB协议版本由SMB1改为SMB3
4.11
2017年4月
支持SMB DFS; 支持SMB3传输加密
3.12
2013年11月
支持SMB 3.0.2
3.8
2013年2月
支持SMB 2.0.2
3.7
2012年12月
支持SMB 2.1
2.5.42
2002年10月
以内核模块形式新增CIFS虚拟文件系统

表-4 Linux内核对SMB协议的支持(SMB客户端)[16]

兼收并蓄是未来

虽然很多人知道,Windows可以连接NFS协议的文件分享,Linux上也可以挂载SMB协议的网络存储。但是大家也都普遍认为,这种“跨平台”的网络文件系统会有很多不可知的问题,性能也不好。在过去的很长的一段时间里,确实大致如此。

不过随着近年来微软和开源社区,特别是和SAMBA的紧密合作,Unix/Linux平台上对SMB协议的支持已经比较完整了,功能和性能上都有了长足的进步。特别是近期在Linux 4.18内核版本中,CIFS客户端增加了SMB 3.1.1版协议对POSIX extension的实验性支持[17]。一直以来,Windows和POSIX的文件系统语义的兼容性问题都在阻碍着用户进行跨平台文件方位(Windows、Linux、MAC等)。而在云计算大发展的当下,Linux系统和Windows系统分别统治消费者市场[18]服务器市场[19],数据和文件的跨平台访问会是一个可以预见的强大需求。随着SMB POSIX extension的到来,必将使SMB协议在跨平台的网络文件访问上得以大展身手。在今天,主要的云计算厂商几乎都已经推出了云上的文件存储服务,用户一般可以使用SMB或者NFS协议来挂载访问这些云文件存储,本文也对各家厂商对SMB和NFS的协议支持情况做了个简单总结(见表-5)供读者参考。

云厂商
产品
SMB​协议支持
NFS协议支持
阿里云
文件存储 NAS
SMB2,SMB3
NFS3,NFS4
亚马逊AWS
EFS
X
NFS4
FSx for Windows File Server
SMB2, SMB3
X
微软Azure
File Storage
SMB3
X
谷歌GCP
Filestore
X
NFS3
腾讯云
文件存储 CFS
SMB1, SMB2, SMB3
NFS3, NFS4
华为云
弹性文件服务 SFS
X (即将上线)
NFS3
*表中资料收集自2018年11月29日

表-5 主要云厂商文件存储产品对SMB和NFS协议的支持

四、写在最后

随着存储行业的发展,云文件存储也会向跨地域大集群的方向发展,如SMB、NFS之类的网络文件系统协议为了不被淘汰出历史舞台,也必然会做出更多的改变。SMB的故事还会继续,我们且继续关注。

参考资料

[1] Myths about Samba
[2] History of the Internet
[3] CIFS acceleration techniques
[4] Stop Using SMB1
[5] 禁用SMB1协议
[6] Common Internet File System Protocol (CIFS/1.0)
[7] MS-SMB2
[8] SMB 2.2 is now SMB 3.0
[9] SMB timeout
[10] Samba team
[11] Redmond Interoperability Plugfest 2018
[12] Samba and the PFIF
[13] Microsoft open source
[14] Microsoft contributes open source code to samba
[15] SAMBA release History
[16] Linux CIFS Kernel
[17] POSIX extension
[18] Desktop OS market share
[19] Server OS market share

上一篇:Consensus On Transaction Commit


下一篇:为苹果ATS和微信小程序搭建 Nginx + HTTPS 服务