unRaid SMB 共享:基于Windows 10 下的 SMB 问题深入分析及解决方式
创作立场声明:本文章首发于SMZDM,转载请注明作者和出处
一、前言:Windows 下的 SMB 问题随处可见
相信大家在使用 unRaid 的 SMB 共享时都会遇到过如下问题(其实抛开 unRaid 不谈,相信大家其他情形下也遇到过):
unRaid 官方论坛上与 SMB 有关的问题也是一抓一大把:
二、目的:分析产生的原因,提供解决思路和办法
本文基于 unRaid 系统为背景,向大家分享UP在使用 unRaid 过程中所了解到的 Windows 下关于 SMB 问题的现象、所产生的原因和解决办法,也希望此文章能起到抛砖引玉的作用,如有不正确的地方请评论区或私信指正,不胜感激!
三、问题的主要原因:Windows 自身的“缺陷”所导致
这个缺陷是:由于 Windows 不允许使用不同的用户名来多次连接到同一个服务器,所以会导致即使访问 SMB 共享文件夹时,即使提供了正确的用户名和密码,也会出现无法访问的情况。
由于 Windows 自身的缺陷(也有人说这是BUG),Windows 下 SMB 的问题从十多年前就一直延续至今,所以无论是搜索引擎还是各种论坛,去搜索SMB问题的关键字可以得到数不尽的各种条目,关于 SMB 的问题都一直没有断过。
后续的内容,UP会站在从零开始一步步去复现这些问题,内容可能会有些长,但是看完之后你会对这一问题有了更清晰的了解,同时你也会知道要如何正确地使用 SMB 共享。
四、准备工作:一个全新的 Window 10 系统,以及一个 unRaid 服务器
1. 准备一个测试用的 Windows 10系统
这里 UP 为了尽可能的排除系统层面的问题干扰(其实不是全新的系统一般问题也不大,我有强迫症 ),我在虚拟机里面新安装了一个 Window 10 (版本 21H1)系统:
系统的用户名为“Jackie”,密码为 123456:
2. 准备 unRaid 系统(只要是 Linux 系统就行)
这里的 unRaid 系统就是 UP 自己的 NAS:
3. 在 unRaid 上创建一个用户
为了方便测试,我们在 unRaid 上创建一个名叫“joker”的用户,密码设置为 123456:
4. 创建 unRaid 上测试用的 SMB 共享文件夹
我们使用同样的方法,创建另一个 SMB 共享文件夹,名称为 “test-private”,这一个文件夹只允许 “joker”这一用户读写:
"Security: Private" 表示此文件夹只有特定的用户可以读写
至此,我们创建好了两个文件夹:
5. 我们一共准备了哪些东西
为了方便大家后续的理解,UP将准备好的系统、用户、文件夹等内容都表示在了下面一张图中:
五、Windows 的自身缺陷:SMB 问题的伊始
我们准备了两个共享文件夹,分别是“test-public”和“test-private”,那么要在 Windows 里面访问这些文件夹,第一种比较常见的方式就是在“网络”面板进行访问:
启用网络发现后,我们在“网络”面板发现了 unRaid 服务器 ——“JACKIEWU”:
双击进入之后我们看到了准备好的两个共享文件夹:
我们可以直接进入“test-public”文件夹,因为此文件夹是一个公共文件夹,所以我们能够在里面创建一个文本文档:
1. “误会”的产生:Windows 是如何与服务器端的 Samba 进行沟通的
首先,什么是 Samba?
Samba 是在 Linux 和 UNIX 系统上实现 SMB 协议的一个免费软件。unRaid 系统自带 Samba 软件,我们上面通过 WebUI 设置的共享文件夹就是通过 Samba 来实现的。
维基百科:Samba,是种用来让UNIX系列的操作系统与微软Windows操作系统的SMB/CIFS(Server Message Block/Common Internet File System)网络协议做链接的自由软件。第三版不仅可访问及分享SMB的文件夹及打印机,本身还可以集成入Windows Server的网域,扮演为网域控制站(Domain Controller)以及加入Active Directory成员。简而言之,此软件在Windows与UNIX系列操作系统之间搭起一座桥梁,让两者的资源可互通有无。
百度百科:Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源。通过设置“NetBIOS over TCP/IP”使得Samba不但能与局域网络主机分享资源,还能与全世界的电脑分享资源。
接着,Windows 与 unRaid 上的 Samba 是如何通信的?
当我们在文件资源管理器中双击 "test-public" 这一文件夹时,Windows 会将本机的名称(hello)、当前用户的用户名( jackie )与本用户的密码(123456)传递给 unRaid 上的 Samba 进行认证,过程如下:
unraid 上的 samba 收到请求后,会去查询 jackie 这个用户是否存在,那么很显然在 unraid 侧是没有这个用户的;并且 samba 也同时会去检测 hello 是否存在(虽然这里的 "hello" 是我们 Windows 10 的主机别名),那么显然也是不存在有 hello 这个用户的。
虽然 samba 对 windows 发过来的用户认证请求没有查询到对应的用户,但是由于我们对共享文件夹设置了公开的属性,因此 samba 会返回认证成功的消息。
但是在服务器侧,samba 会将 windows 后续的进一步请求,在服务器侧关联为 “nobody” 这一用户。
也就是说在这种情况下,由于 samba 不认识 "hello/jackie" 这个用户,所以 unraid 上的 samba 会将 "hello/jackie" 视为服务器上的 "nobody" 用户。
我们如何知道这一点?
我们通过SSH连接到 unRaid 之后,输入命令 smbstatus ,得到的输出结果如下:
此时我们可以看到,Samba 将我们的 Windows (ip地址:10.10.10.55)视为 "nobody" 。
这时候引出了一个问题,或者说 “误会”:
① 对于 Windows 来说:由于服务器返回了认证成功的消息,所以 Windows 就认为提交过去的认证信息是正确的,此时就会把这一结果存储到 Windows 自身的证书缓存(credentials cache),这个证书上的用户就是 "hello/jackie" ,证书的密码是 123456。
② 对于服务器来说:服务器没有这个用户,所以将 Windows 视为 "nobody" 用户。
所以大家看出问题来了吗:Windows 以为服务器认识它 ,把认证信息存储到了它自己的证书缓存中 ,然后每一次去访问服务器的共享文件夹就拿着这张证书去做认证,但实际上服务器不认识这个人 (视为 "nobody" )。
2. 当"误会"变成"矛盾":Windows 禁止对共享资源的多重连接
如果只是访问公开的共享文件夹,这个“误会”是不会有什么影响的,毕竟公开的文件夹大家都可以访问,你想干嘛就干嘛,服务器也不管你。
但是如果说此时 Windows 要访问一个私有的文件夹(对应到我们本文来说就是 "test-private" 文件夹),由于私有文件夹只对特定的用户(对应本文就是 "joker" )提供读写的权限,所以当 Windows 再拿着原来的证书信息去访问时,很显然服务器就不会给你通过认证了。
我们继续以例子做说明,请往下看。
首先,我们打开的 "test-public" 文件夹并放一边,然后我们去访问 "test-private" 文件夹:
同样,我们访问 "test-private" 文件夹时,也需要向服务器发送认证信息(过程跟上面我们去访问 "test-public" 文件夹一样),但是此时服务器收到信息后发现 Windows 提交的信息不符,因为很显然 "hello/jackie" 并不在 "test-private" 文件夹的授权用户列表中(只有 "joker" 这一用户被授权),因此服务器会返回认证失败的信息。
那么此时,windows 就会弹出账号密码的输入框,需要你提供可以通过服务器认证的用户名和密码。
然后我们输入正确的用户名 "joker" 以及正确的密码 "123456":
但是此时问题出现了,windows 不允许我们访问,理由是“不允许一个用户使用一个以上用户名与服务器或共享资源的多重连......”,即使我们已经输入了正确的用户名和密码 。
为什么会这样?让我们来回顾一下:
① 我们刚才打开了 "test-public" 文件夹并放到了一边,这个动作的背后即 windows 以 "hello/jackie" 的身份去向服务器(unRaid)发起请求并通过了认证,然后访问到了文件夹中的内容。
② 此时我们没有关闭 "test-public" 文件夹(没有结束访问),这时候我们去访问 "test-private" 文件夹并输入了正确的用户名(joker)和密码(123456)提交给服务器做认证,提交后却弹出错误提示。
为什么会这样?
是因为 Windows 发现我们一边以 "hello/jackie" 的身份去访问 "test-public" 文件夹,同时另一边用 "joker" 的身份去访问 "test-public" ,并且这两个文件夹都属于同一个服务器,此时 Windows 就提示你“不允许一个用户使用一个以上用户名与服务器或共享资源的多重连”。
没错,Windows 不允许你在同一时间用不同的身份访问同一个服务器上的多个资源(产生多个连接)
我相信很多人都会卡在上面的第 ② 步——反反复复输入账号密码却一直被弹出错误提示,然后一个个字符去检查到底是用户名错了还是密码错了,查了半天还是没找出原因,我相信不少同学都体会过这种痛苦 。
这也就是为什么说这个现象是 Windows 自身的一个“缺陷”(甚至说是 BUG)了。
六、解决办法/技巧
1. 技巧:通过 IP 地址访问的形式来“欺骗”Windows
这里有一个小技巧,我们可以通过 IP 地址访问的形式欺骗 Windows,让 Windows 误以为我们访问的不是同一个服务器。
此方式仅仅是个小技巧,要真正一劳永逸解决此问题,还请看后面的方法一和方法二,但是通过了解此技巧能让你更好的了解 Windows 上的这些 SMB 问题。
由于 Windows 不允许我们在同一时间内以不同的身份向同一个服务器发起多重连接,那么我们可以通过 IP 地址的形式去访问 "test-private" 文件夹,而不是在 "网络" 面板中去直接访问,这样可以起到一个“欺骗”作用——让 Windows 误以为我们访问的是不同的服务器:
在文件资源管理器的地址栏直接使用双反斜杠并输入服务器地址和文件夹
为了验证这一说法,我们继续测试
在测试前,为了能够使方法生效,需要先注销当前用户,确保断开所有与服务器的连接,然后再重新登录后再去进行操作。
或者也可以通过 CMD 命令,输入 net use * /delete 命令来断开所有与服务器的连接,不过直接注销用户会更彻底一些。
请看下面的这个 Gif:我们通过“网络”面板,在已经打开 "test-public" 文件夹的情况下,再通过 ip 地址打开 "test-private" 文件夹时就可以实现正常访问了:
如果你发现没有实现这一效果,那么可能在服务器端 Samba 没有彻底与 Windows 断开连接,此时可以通过 SSH 连接到 unRaid ,然后使用以下命令从服务器端彻底与 Windows 断开连接(后面的 ip 地址填写 Windows 的 ip 地址):
smbcontrol smbd kill-client-ip 10.10.10.55
2. 方法一:先访问私有文件夹,以此来建立正确的证书缓存
上面的小技巧通过 ip 地址的方式来“欺骗”了 Windows,但也仅仅是个技巧,毕竟不能真正的解决这类问题。
这里的方法一的原理,是先访问 "test-private" 并提供验证信息(用户名 "joker" 和密码 123456)来通过服务器的认证,Windwos 收到验证通过的信息后,把用户名 "joker" 和密码 123456 存入到了证书缓存中。
这样一来,后续无论是访问 "test-private" 还是 "test-public" 文件夹,都会以 "joker" 这个证书信息去提交给服务器进行验证,因此就能够正确得到服务器的授权了。
换而言之就是不要先访问 "test-public" 这一个公共文件夹(因为 Windows 会把自己的用户名和密码放到证书缓存中),而是先访问 "test-private" 这一私有文件夹。
我们要做的,就仅仅是改变一下访问的顺序即可,但产生的差别可以看出来是有多大 。
但要说明的是,这个还不是最优的方法,请看下面的方法二。
3. 方法二:手动创建证书
通过上面的技巧和方法,相信你已经能够对整个解决的过程有了比较深入的理解,因此 UP 才把最终的解决手段放到最后去展示。
我们前面知道,当 Windows 第一次去访问服务器时都会发送认证信息,当通过授权后 Windows 会把“它认为”可以通过认证的信息存入到证书缓存中,以便后续的访问都能够直接拿这一证书去提交给服务器认证。
但实际上我们是可以自己手动创建一个证书,这样一来就不用 Windows 自己去生成证书(毕竟猪脑子 ),而是由我们指定访问某一个服务器时要用哪一个证书。
点击开始按钮,输入“凭据”:
这里要注意了,我们证书上的服务器地址填的是 ip 地址(10.10.10.3),如果我还是通过“网络”面板去访问 unRaid 服务器("JACKIEWU"),那么在 Windows 看来这依然是两个不同的服务器,我们的证书就不会起作用了。
如果需要使用网络面板的形式,那么证书的服务器地址就不应该是 ip 地址,而应该是 "JACKIEWU"(大小写无所谓,Windows 对大小写不敏感):
你只需要再添加一份以"JACKIEWU"为服务器地址的证书即可,但是没有必要
但是UP是非常不建议通过 "网络" 面板去访问我们在服务器上的 smb 共享资源的,而是应该通过“网络驱动器映射”的方式来更直接的访问共享文件:
从上面的动图可以看到,我们访问 "test-private" 时已经不需要输入用户名和密码了,也能够正常读写文件。并且,我们从服务器侧去查看,可以看到我们的用户身份是 "joker" :
七、知识点巩固:当 Windows 的用户名与服务器的用户名相同
相信大家对 Windows 与 Linux 上 Samba 的通信过程、Windows 自身的处理机制都有了一定的了解。为了给大家巩固知识点,UP 这里插入另一个知识点:
我们假设,服务器上的用户与我们 Windows 用户的用户名字是一样的,比如说 Windows 用户的用户名是 "jackie",服务器上的用户也是叫 "jackie",但是两者的用户密码是不一样。
当我们从 Windows 上去访问 "test-public" 这个公共文件夹时,会发生需要你输入账号密码的情况。
是不是很疑惑?为什么一个公共的文件夹还需要提供用户和密码?我们之前访问的时候不是好好的么?
我们回顾一下前面的知识点:
所以,看明白了吗?
由于服务器也存在一个叫 "jackie" 的用户,所以这时候服务器就不会把 Windows 关联为 "nobody" 了,而是进一步核对密码是否正确,但是由于服务器上的 "jackie" 的用户密码跟 Windows 上的 "jackie" 不一样,所以这时候服务器就会返回认证不通过的信息,这也就是为什么 Windows 弹出账号密码输入框了。
这种情况对用户来说可能更不友好,因为这时候大多数人都会输入 Windows 上用户的用户密码,而不是服务器端用户的用户密码,所以很多人就会抓狂:我明明输入了对了密码(Windows 端),为什么还是没有通过验证?结果最后才发现你给过去的密码不是服务器端想要的。
八、结尾
好了,看到这里首先感谢大家的耐心,能完整看下来的同学相信应该有所收获,如果 UP 有哪里说错了,恳请在评论区告知。如果你觉得 UP 的内容有用,也请点个赞(打赏的话就更好了 )。
本篇内容所涉及到的核心知识,是 UP 在 unRaid 官方论坛以及相关视频资料了解到的,相关的内容连接如下:
Unraid Shares in Depth - PT1 Windows and SMB - Problems & Solutions
转载请注明作者和出处,谢谢。
(完)
laozengge
这个问题我特意去unraid论坛问了才知道,中文网络都搜索不到。
只需要在unraid的设置-SMB-SMB额外
添加参数:map to guest = Never
校验提示文案
AlDa
校验提示文案
MJSin
校验提示文案
伊一线天
校验提示文案
everett
校验提示文案
值友3333862156
校验提示文案
Vchenseoul
校验提示文案
Vchenseoul
校验提示文案
陆平平
校验提示文案
rhww
校验提示文案
无人熟悉大菠萝
校验提示文案
楼船夜雪瓜洲渡
校验提示文案
不辣的啤特
校验提示文案
bowencool
校验提示文案
kevin_zhu_sh
校验提示文案
piscesc
校验提示文案
疯狂的门徒
校验提示文案
值友9559324936
校验提示文案
哈雷哥特
校验提示文案
绫林鸟
校验提示文案
laozengge
这个问题我特意去unraid论坛问了才知道,中文网络都搜索不到。
只需要在unraid的设置-SMB-SMB额外
添加参数:map to guest = Never
校验提示文案
两个字
校验提示文案
坐骨神经痛
校验提示文案
啥都想买但没钱
校验提示文案
陆平平
校验提示文案
梦太晓
后来多翻查资料才解决,这篇文章分析的很到位
校验提示文案
慕倚竹
校验提示文案
剃了剃头
校验提示文案
嘲笑的风
校验提示文案
艾德森
校验提示文案
绫林鸟
校验提示文案
哈雷哥特
校验提示文案
值友9559324936
校验提示文案
疯狂的门徒
校验提示文案
无人熟悉大菠萝
校验提示文案
piscesc
校验提示文案
kevin_zhu_sh
校验提示文案
Vchenseoul
校验提示文案
Vchenseoul
校验提示文案
bowencool
校验提示文案