这篇你能学到#
- 怎么用
smbclient / mount.cifs / net use / Get-SmbConnection 把 SMB 共享"连起来、看进去",以及 smb.conf 里哪些开关决定安全与性能。 - 怎么用 Wireshark
smb2 过滤式从 NEGOTIATE → SESSION_SETUP → TREE_CONNECT 抓包,一眼区分"版本协商失败 / 认证失败 / 共享级还是文件系统级权限不足"。 - 遇到
LOGON_FAILURE、ACCESS_DENIED、BAD_NETWORK_NAME、版本协商失败、文件被占用、性能差时先记结论再排查,以及 SMB1/EternalBlue 的加固清单与和 NFS 的选型对比。
抓包观察#
Wireshark 显示过滤式#
下面这些过滤式是 SMB 排错的"目录",先扫一眼:看到 smb 说明环境里还有 SMB1(应立即整改),smb2.nt_status != 0 是看错误响应的第一过滤式,smb2.dialect 能确认有没有被降级。
| 过滤式 | 用途 |
|---|
smb2 | 所有 SMB2/3 报文(最常用) |
smb | SMB1 报文 —— 抓到就说明环境里还有 SMB1,应立即整改 |
tcp.port == 445 | Direct Hosting |
tcp.port == 139 | SMB over NetBIOS(旧) |
nbns | NetBIOS 名称服务(UDP 137)—— Responder 投毒的信号 |
smb2.cmd == 0 | 只看 NEGOTIATE(排查版本协商失败) |
smb2.cmd == 1 | 只看 SESSION_SETUP(排查认证问题) |
smb2.cmd == 3 | 只看 TREE_CONNECT(排查共享名/共享权限) |
smb2.cmd == 5 | 只看 CREATE(打开文件) |
smb2.cmd == 8 || smb2.cmd == 9 | 只看 READ / WRITE(性能分析) |
smb2.nt_status != 0 | 只看出错的响应,排错第一过滤式 |
smb2.nt_status == 0xc000006d | STATUS_LOGON_FAILURE(密码错,暴力破解检测) |
smb2.nt_status == 0xc0000022 | STATUS_ACCESS_DENIED(权限不足) |
smb2.nt_status == 0xc00000cc | STATUS_BAD_NETWORK_NAME(共享名不存在) |
smb2.nt_status == 0xc0000043 | STATUS_SHARING_VIOLATION(文件被占用) |
smb2.dialect | 协商出的方言版本 |
smb2.filename contains "report" | 按文件名筛 |
smb2.tree contains "IPC$" | 谁在访问 IPC$(横向移动检测) |
ntlmssp | NTLM 认证交换(看挑战/响应) |
kerberos | Kerberos 认证 |
smb2.flags.signature == 1 | 已签名的报文 |
smb2.protocol_id == 0xfd534d42 | 加密的 SMB3 报文(TRANSFORM_HEADER) |
smb2.time > 1 | 响应超过 1 秒的慢请求 |
命令行抓包:下面这套 tcpdump/tshark 覆盖"抓全量、捞错误、查 SMB1、统计认证失败来源、确认协商方言、SMB 性能统计"六个动作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| sudo tcpdump -i eth0 -s 0 -w smb.pcap 'port 445 or port 139 or port 137'
# 找出所有失败的 SMB2 操作
tshark -r smb.pcap -Y 'smb2.nt_status != 0' -T fields \
-e frame.number -e ip.src -e ip.dst -e smb2.cmd -e smb2.nt_status -e smb2.filename
# 检测环境中是否还有 SMB1(安全审计必做)
tshark -r smb.pcap -Y 'smb' -T fields -e ip.src -e ip.dst | sort -u
# 统计认证失败来源(口令喷洒检测)
tshark -r smb.pcap -Y 'smb2.nt_status == 0xc000006d' -T fields -e ip.src | sort | uniq -c | sort -rn
# 看协商出的方言(确认没有降级)
tshark -r smb.pcap -Y 'smb2.cmd == 0 && smb2.flags.response == 1' \
-T fields -e ip.src -e smb2.dialect
# SMB 性能统计(Wireshark 内置)
tshark -r smb.pcap -q -z smb2,srt
|
典型字段说明#
NEGOTIATE Response(确认协商结果):重点看 Dialect 是不是 3.1.1、Signing required 是不是 True、Cipher 是什么——这三项直接反映服务端安全水位。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| SMB2 (Server Message Block Protocol version 2)
SMB2 Header
Server Component: SMB2 (0xfe534d42) ← 0xFE = SMB2/3;0xFF = SMB1;0xFD = 已加密
Header Length: 64
Command: Negotiate Protocol (0)
NT Status: STATUS_SUCCESS (0x00000000)
Credits granted: 1
Flags: 0x00000001 .... ...1 = Response: This is a RESPONSE
Message ID: 0
Negotiate Protocol Response (0x00)
Security mode: 0x03
.... ...1 = Signing enabled: True
.... ..1. = Signing required: True ← 服务器【要求】签名
Dialect: 0x0311 ← 协商出 SMB 3.1.1 ✅
Capabilities: 0x0000007f
... DFS / LEASING / LARGE_MTU / MULTI_CHANNEL / ENCRYPTION
Negotiate Context: SMB2_PREAUTH_INTEGRITY_CAPABILITIES
HashAlgorithm: SHA-512
Negotiate Context: SMB2_ENCRYPTION_CAPABILITIES
Cipher: AES-128-GCM ← 加密算法
|
NTLMSSP 认证三步(工作组/IP 直连时可见):注意用户名是明文、NTLMv2 响应可被离线爆破或 Relay。
1
2
3
4
5
6
7
8
9
| ① SESSION_SETUP Request → NTLMSSP_NEGOTIATE (messageType=1)
② SESSION_SETUP Response → NTLMSSP_CHALLENGE (messageType=2)
NTLM Server Challenge: 1122334455667788 ← 8 字节挑战值
Target Name: WORKGROUP
③ SESSION_SETUP Request → NTLMSSP_AUTH (messageType=3)
Domain name: EXAMPLE
User name: administrator ← 用户名明文可见
NTLMv2 Response: <HMAC-MD5 结果> ← 可离线爆破 / 可被 Relay
④ SESSION_SETUP Response → STATUS_SUCCESS + SessionId
|
排错四看:
- NEGOTIATE 响应的
Dialect:确认协商到的版本。若是 0x0202 或看到 SMB1,说明一端太老或被降级。 - SESSION_SETUP 的
NT Status:0xC0000016 MORE_PROCESSING_REQUIRED 是 NTLM 多轮的正常中间态,不是错误;最终变 SUCCESS 才算认证通过。 - TREE_CONNECT 的
NT Status:0xC00000CC = 共享名错;0xC0000022 = 共享级权限不足。这一步能区分"共享权限"和"NTFS 权限" —— 能 TREE_CONNECT 成功但 CREATE 失败,说明是 NTFS ACL 问题。 - 有没有
TRANSFORM_HEADER(0xFD534D42):有 = SMB3 加密生效,Wireshark 看不到内容(这是好事)。
常用命令 / 配置#
Linux 客户端#
下面这组是 Linux 侧"装工具 → 探共享 → 交互访问 → 挂载"的常规动作;其中 -m SMB1/SMB2/SMB3 还能用来试探服务端支持哪些版本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
| # 安装
sudo apt install smbclient cifs-utils # Debian/Ubuntu
sudo yum install samba-client cifs-utils # RHEL/Rocky
# ---------- 探测 ----------
# 列出共享(匿名)
smbclient -L //192.168.1.100 -N
# 列出共享(指定凭据 + 强制 SMB3)
smbclient -L //192.168.1.100 -U 'EXAMPLE\zhangsan' -m SMB3
# 只探测支持的协议版本(排查版本问题)
smbclient -L //192.168.1.100 -N -m SMB1 # 若成功 = 服务端还开着 SMB1 smbclient -L //192.168.1.100 -N -m SMB2
smbclient -L //192.168.1.100 -N -m SMB3
# nmap 全面探测(版本、共享、漏洞)
nmap -p 445 --script smb-protocols,smb-security-mode,smb-os-discovery 192.168.1.100
nmap -p 445 --script smb-enum-shares,smb-enum-users 192.168.1.100
nmap -p 445 --script smb-vuln-ms17-010 192.168.1.100 # EternalBlue 检测
# ---------- 交互式访问(类 FTP)----------
smbclient //192.168.1.100/share -U 'EXAMPLE\zhangsan'
# smb: \> ls
# smb: \> cd docs
# smb: \> get report.docx
# smb: \> put local.txt
# smb: \> mget *.log
# smb: \> prompt off # 关闭 mget/mput 的逐个确认
# smb: \> recurse on # 递归
# smb: \> mask ""
# smb: \> exit
# 非交互执行命令(脚本用)
smbclient //192.168.1.100/share -U 'user%password' -c 'ls; get report.docx'
# 用凭据文件(避免密码进 history 和 ps)
cat > ~/.smbcreds <<'EOF'
username=zhangsan
password=P@ssw0rd
domain=EXAMPLE
EOF
chmod 600 ~/.smbcreds
smbclient //192.168.1.100/share --authentication-file=~/.smbcreds
# ---------- 挂载到本地 ----------
sudo mkdir -p /mnt/smb
sudo mount -t cifs //192.168.1.100/share /mnt/smb \
-o credentials=/root/.smbcreds,vers=3.1.1,uid=1000,gid=1000,file_mode=0644,dir_mode=0755,iocharset=utf8,seal
# 常用挂载参数:
# vers=3.1.1|3.0|2.1|2.0 协议版本(不指定则自动协商,建议显式指定)
# credentials=<file> 凭据文件
# uid=/gid= Linux 侧文件属主(SMB 无 POSIX 属主概念,必须映射)
# file_mode=/dir_mode= Linux 侧权限位
# iocharset=utf8 中文文件名必需
# seal 【强制 SMB3 加密】
# sec=ntlmssp|krb5 认证方式
# noperm 不做本地权限检查(交给服务器判断)
# cache=strict|none|loose 缓存策略
# actimeo=1 属性缓存秒数(默认 1)
# nobrl 禁用字节范围锁(某些应用需要)
# _netdev fstab 中标记网络设备
sudo umount /mnt/smb
# fstab 持久化
# //192.168.1.100/share /mnt/smb cifs credentials=/root/.smbcreds,vers=3.1.1,uid=1000,gid=1000,iocharset=utf8,seal,_netdev,x-systemd.automount 0 0
# ---------- Kerberos 挂载(域环境)----------
kinit zhangsan@EXAMPLE.COM
sudo mount -t cifs //fs01.example.com/share /mnt/smb -o sec=krb5,cruid=$(id -u),vers=3.1.1
|
Windows 客户端(PowerShell 优先)#
下面这组 Windows 侧命令里,Get-SmbConnection 能直接看到协商到的 Dialect 和是否加密签名,是诊断首选。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| # ---------- 探测与连接 ----------
net view \\192.168.1.100 # 列出共享(依赖 srvsvc)
net use Z: \\192.168.1.100\share /user:EXAMPLE\zhangsan *
net use # 查看当前映射
net use Z: /delete # 断开
net use * /delete /y # 断开全部
# PowerShell 方式(推荐)
New-SmbMapping -LocalPath 'Z:' -RemotePath '\\192.168.1.100\share' `
-UserName 'EXAMPLE\zhangsan' -Password 'P@ssw0rd' -Persistent $true
Remove-SmbMapping -LocalPath 'Z:' -Force
# ---------- 诊断(最有用的几条)----------
Get-SmbConnection # 当前连接【含协商出的 Dialect】Get-SmbConnection | Format-Table ServerName,ShareName,Dialect,Encrypted,Signed
Get-SmbMultichannelConnection # 多通道状态
Get-SmbClientNetworkInterface # 客户端网卡与 RSS/RDMA 能力
Get-SmbClientConfiguration # 客户端全局配置
Get-SmbOpenFile # 服务端:谁打开了哪些文件 Get-SmbSession # 服务端:当前会话
Get-SmbShare # 服务端:本机共享列表
Get-SmbShareAccess -Name 'share' # 共享级权限(不是 NTFS 权限!)
# ---------- 服务端配置 ----------
New-SmbShare -Name 'data' -Path 'D:\data' -FullAccess 'EXAMPLE\Admins' -ReadAccess 'EXAMPLE\Users'
Set-SmbShare -Name 'data' -EncryptData $true # 该共享强制 SMB3 加密
Grant-SmbShareAccess -Name 'data' -AccountName 'EXAMPLE\zhangsan' -AccessRight Change -Force
Revoke-SmbShareAccess -Name 'data' -AccountName 'Everyone' -Force
Remove-SmbShare -Name 'data' -Force
# 全局强制加密与签名
Set-SmbServerConfiguration -EncryptData $true -Force
Set-SmbServerConfiguration -RequireSecuritySignature $true -Force
Set-SmbClientConfiguration -RequireSecuritySignature $true -Force
# ---------- 禁用 SMB1(安全加固,必做)----------
Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol # 查状态
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
Get-SmbServerConfiguration | Select EnableSMB1Protocol
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
# 审计谁还在用 SMB1(先审计再禁用,避免误伤老设备)
Set-SmbServerConfiguration -AuditSmb1Access $true -Force
Get-WinEvent -LogName 'Microsoft-Windows-SMBServer/Audit' -MaxEvents 50
|
Linux 服务端(Samba)#
装好 Samba 后,真正的重点在 smb.conf:下面这份配置同时做了"禁 SMB1、强制签名加密、禁空会话、禁 NTLMv1"四项加固。
/etc/samba/smb.conf:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| [global]
workgroup = EXAMPLE
server string = File Server
security = user
map to guest = Never
# ---- 协议版本:禁用 SMB1,只允许 SMB2/3 ----
server min protocol = SMB2_10
server max protocol = SMB3_11
client min protocol = SMB2_10
# ---- 安全加固 ----
server signing = mandatory # 强制签名
smb encrypt = required # 强制 SMB3 加密(desired = 尽量加密)
restrict anonymous = 2 # 禁止空会话
ntlm auth = no # 只允许 NTLMv2(禁 NTLMv1)
# ---- 性能 ----
socket options = TCP_NODELAY IPTOS_LOWDELAY
use sendfile = yes
aio read size = 16384
aio write size = 16384
# ---- 日志 ----
log file = /var/log/samba/log.%m
max log size = 5000
log level = 1
[data]
path = /srv/samba/data
browseable = yes
read only = no
valid users = @smbusers
create mask = 0664
directory mask = 0775
force group = smbusers
veto files = /.DS_Store/Thumbs.db/
[public]
path = /srv/samba/public
browseable = yes
read only = yes
guest ok = yes
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # 校验配置语法(改完必做)
testparm
testparm -s # 只输出有效配置(含默认值)
# 用户管理(Samba 密码库与 Linux 密码独立!)
sudo useradd -M -s /sbin/nologin zhangsan
sudo smbpasswd -a zhangsan # 添加到 Samba 密码库
sudo smbpasswd -e zhangsan # 启用
sudo pdbedit -L -v # 列出所有 Samba 用户
sudo systemctl restart smbd nmbd
sudo systemctl status smbd
# 运行状态
sudo smbstatus # 当前连接、锁定的文件 sudo smbstatus -b # 只看会话
sudo smbstatus -L # 只看锁
# 日志
sudo tail -f /var/log/samba/log.smbd
|
常见故障与排错#
故障 1:NT_STATUS_LOGON_FAILURE —— 认证失败#
先记住结论:认证失败先怀疑"密码 / 域名写法 / Samba 独立密码库不同步"这三样,Kerberos 场景还要看两端时差是否超 5 分钟。Samba 的密码库和 Linux 系统密码是两套,改了系统密码不等于 Samba 能用。
| 原因 | 排查 |
|---|
| 密码错 | 换个已知正确的账号试 |
| 域名写法错 | 试 EXAMPLE\user、user@example.com、纯 user 三种写法 |
| Samba 密码库与系统密码不同步 | sudo smbpasswd -a user 重设(Samba 有独立密码库!) |
| 账号被禁用/锁定/密码过期 | Windows:net user zhangsan /domain;Samba:pdbedit -L -v |
| NTLMv1 被禁但客户端只支持 v1 | 服务端日志会有提示;老设备需临时 ntlm auth = yes(不推荐) |
| 时间不同步(Kerberos) | Kerberos 要求两端时差 < 5 分钟,chronyc sources / w32tm /query /status |
| 用 IP 连导致回落 NTLM 而域策略禁止 | 改用 FQDN 连接以走 Kerberos |
1
2
3
4
| # 提高 Samba 日志级别定位
sudo smbcontrol smbd debug 5
sudo tail -f /var/log/samba/log.smbd
sudo smbcontrol smbd debug 1 # 记得调回去
|
故障 2:NT_STATUS_ACCESS_DENIED —— 认证过了但访问不了#
先记住结论:SMB 是两层权限取交集——共享级(TREE_CONNECT 阶段检查)和文件系统级(CREATE 阶段检查)。一眼区分法:TREE_CONNECT 就拒是共享级问题;连上了 CREATE 才拒是 NTFS/POSIX 问题(Samba 上还常是 SELinux 上下文没设 samba_share_t)。
关键:Windows/Samba 有两层权限,取交集(更严格的那个生效):
1
2
3
| ① 共享级权限(Share Permissions) ← TREE_CONNECT 阶段检查
② NTFS / POSIX 文件系统权限 ← CREATE 阶段检查
最终权限 = ① ∩ ②
|
用抓包精确定位是哪一层:
TREE_CONNECT 就返回 0xC0000022 → 共享级权限问题TREE_CONNECT 成功但 CREATE 返回 0xC0000022 → NTFS/POSIX 权限问题
1
2
3
4
| # Windows:查两层权限
Get-SmbShareAccess -Name 'data' # 共享级
Get-Acl 'D:\data' | Format-List # NTFS 级
(Get-Acl 'D:\data').Access | Format-Table IdentityReference,FileSystemRights,AccessControlType
|
1
2
3
4
5
6
7
8
9
10
11
| # Linux/Samba:查两层
testparm -s | grep -A10 '\[data\]' # 共享级:valid users / read only
ls -ld /srv/samba/data # POSIX 级
getfacl /srv/samba/data # POSIX ACL
ls -Z /srv/samba/data # SELinux 上下文
# SELinux 是 Samba 最常见的隐形杀手
sudo setsebool -P samba_export_all_rw on
sudo chcon -R -t samba_share_t /srv/samba/data
sudo semanage fcontext -a -t samba_share_t "/srv/samba/data(/.*)?"
sudo restorecon -Rv /srv/samba/data
|
故障 3:NT_STATUS_BAD_NETWORK_NAME —— 共享名不存在#
先记住结论:这是共享名拼错或共享不存在,先 smbclient -L 列一遍确认真实共享名;隐藏共享($ 结尾)不会出现在列表里需直接指定。
1
| smbclient -L //192.168.1.100 -U user # 先确认共享名拼写
|
| 原因 | 排查 |
|---|
| 共享名拼错/大小写 | SMB 共享名不区分大小写但要拼对 |
共享是隐藏共享($ 结尾) | C$、ADMIN$、IPC$ 不会出现在列表里,需直接指定 |
Samba 里 path 指向的目录不存在 | testparm + ls -ld <path> |
| 共享被删除或服务未重启 | systemctl restart smbd |
故障 4:连接失败 / 版本协商问题#
先记住结论:版本协商失败九成是"一端还发 SMB1、另一端已禁"(或反过来)。逐版本 smbclient -m SMB1/SMB2/SMB3 试探,就能定位服务端支持范围;Windows 10/11 默认不装 SMB1 连老 NAS 失败时,别重新开 SMB1,去升级 NAS。
1
2
| Protocol negotiation failed: NT_STATUS_CONNECTION_RESET
Unable to connect with SMB1 -- no workgroup available
|
| 原因 | 排查 |
|---|
| 服务端禁用了 SMB1,客户端只发 SMB1 | 客户端加 -m SMB3;升级客户端;老设备(老打印机、老 NAS)需单独隔离 |
| 客户端太老不支持 SMB2 | 检查 smbclient -L //host -m SMB2 是否成功 |
| Windows 10/11 默认不装 SMB1,连老 NAS 失败 | 优先升级 NAS 固件;不要为此重新启用 SMB1 |
| 3.1.1 预认证算法不匹配 | 0xC05D0000,两端 Samba/Windows 版本差异大时出现 |
1
2
3
4
5
| # 逐版本试探,定位服务端支持范围
for v in SMB1 SMB2 SMB3; do
echo "--- $v ---"
smbclient -L //192.168.1.100 -N -m $v 2>&1 | head -3
done
|
故障 5:端口不通#
先记住结论:445 不通先分"服务没起 / 防火墙 / 被 ISP 封"三类;家宽普遍封 445,公网跑 SMB 既不可行也不应该,用 VPN 或 SMB over QUIC。
1
2
3
| nc -zv 192.168.1.100 445
nc -zv 192.168.1.100 139
nmap -p 139,445 192.168.1.100
|
| 原因 | 排查 |
|---|
| Windows 防火墙 | Enable-NetFirewallRule -DisplayGroup "File and Printer Sharing" |
| ISP 封禁 445(家宽普遍) | 公网访问 SMB 不可行也不应该,用 VPN 或 SMB over QUIC |
| Samba 服务未启动 | systemctl status smbd、ss -tlnp | grep 445 |
| Samba 只绑定了部分接口 | smb.conf 的 interfaces / bind interfaces only |
故障 6:中文文件名乱码#
先记住结论:中文乱码几乎都是字符集没对齐——Linux 挂载必须加 iocharset=utf8,服务端 unix charset = UTF-8,并确认系统 locale 是 UTF-8。
1
2
3
4
5
6
7
8
9
10
11
| # Linux 挂载必须加 iocharset
sudo mount -t cifs //host/share /mnt/smb -o credentials=/root/.smbcreds,iocharset=utf8
# Samba 服务端
# smb.conf:
# unix charset = UTF-8
# dos charset = CP936 # 仅当需要兼容极老的中文 Windows 客户端
# 确认系统 locale
locale
export LANG=zh_CN.UTF-8
|
故障 7:STATUS_SHARING_VIOLATION —— 文件被占用#
先记住结论:这正是 Windows 强制锁的"特性"而非故障——某进程以 ShareAccess=0 独占打开文件,别人连读都被拒,这是 Unix 没有的语义。定位是谁占着,必要时由服务端强制关闭句柄。
这是 Windows 语义与 Unix 语义的根本差异:Windows 的 CreateFile 带 ShareAccess 参数,若某进程以 ShareAccess=0 打开文件,其他人连读都打不开。Unix 则允许任意并发打开。
1
2
3
| # 服务端定位是谁占着
Get-SmbOpenFile | Where-Object Path -like '*report.docx*' | Format-Table ClientUserName,ClientComputerName,Path
Close-SmbOpenFile -FileId <ID> -Force # 强制关闭(可能导致对方数据丢失)
|
1
2
| # Samba 侧
sudo smbstatus -L # 看锁定的文件
|
故障 8:性能问题#
先记住结论:性能差先确认协商到的版本——还在 SMB 2.0 就没有大 MTU、单连接跑不满万兆就开 Multichannel、海量小文件慢是 SMB 固有短板(靠复合请求+Lease 缓解,改不了本质)。加密掉速就升到 3.1.1 的 AES-GCM,几乎免费。
1
2
3
| # 确认协商到的版本与特性(旧版本性能差很多)
Get-SmbConnection | Format-Table ServerName,ShareName,Dialect,Encrypted,NumOpens
Get-SmbMultichannelConnection # 多通道是否生效
|
| 症状 | 原因 | 解决 |
|---|
| 大文件传输慢 | 协商到 SMB 2.0,无大 MTU | 升级两端到 SMB3 |
| 万兆网跑不满 | 单连接单核瓶颈 | 启用 Multichannel(多网卡或 RSS 网卡);Set-SmbClientConfiguration -EnableMultiChannel $true |
| 海量小文件极慢 | 每个文件多次 RTT | SMB 的固有短板;用压缩打包传输;确认复合请求生效(SMB2+);启用 Lease 缓存 |
| 开启加密后掉速 | AES 运算开销 | 确认 CPU 支持 AES-NI;SMB3.1.1 的 AES-128-GCM 比 3.0 的 CCM 快得多,升级到 3.1.1 |
| Linux 挂载慢 | 缓存策略 | 调 cache=loose(牺牲一致性)、actimeo=30、rsize/wsize=1048576 |
| 目录列表慢 | 目录项太多 | SMB 的 QUERY_DIRECTORY 分批返回;减少单目录文件数 |
1
2
3
| # Linux 侧看统计
cat /proc/fs/cifs/Stats
sudo mount -t cifs ... -o rsize=1048576,wsize=1048576,cache=strict
|
故障 9:安全加固清单#
先记住结论:SMB 是勒索软件和横向移动的头号通道(WannaCry / NotPetya / EternalBlue 全走 SMB1),加固顺序永远是"禁 SMB1 → 强制签名加密 → 445 不出内网"。网络层那一条(禁止工作站之间互连 445、445 不出边界)能挡掉 90% 的横向传播。
SMB 是勒索软件和横向移动的头号通道(WannaCry / NotPetya / EternalBlue MS17-010 全走 SMB1)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # ===== Windows =====
# ① 禁用 SMB1(最重要)
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
# ② 强制签名(防中间人篡改与 NTLM Relay)
Set-SmbServerConfiguration -RequireSecuritySignature $true -Force
Set-SmbClientConfiguration -RequireSecuritySignature $true -Force
# ③ 强制加密(防窃听)
Set-SmbServerConfiguration -EncryptData $true -Force
Set-SmbServerConfiguration -RejectUnencryptedAccess $true -Force
# ④ 禁用 Guest 回落(防止误连到伪造服务器)
Set-SmbClientConfiguration -EnableInsecureGuestLogons $false -Force
# ⑤ 关闭 NetBIOS over TCP/IP(消除 NBT-NS 投毒面)
Get-NetAdapter | ForEach-Object {
$key = "HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\Tcpip_$($_.InterfaceGuid)"
Set-ItemProperty -Path $key -Name NetbiosOptions -Value 2
}
# 同时在组策略中禁用 LLMNR 和 mDNS
# ⑥ 关闭不必要的管理共享(评估影响后再做)
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters' AutoShareServer 0
|
1
2
3
4
5
6
7
8
9
| # ===== Samba(smb.conf)=====
[global]
server min protocol = SMB2_10 # 禁 SMB1
server signing = mandatory # 强制签名
smb encrypt = required # 强制加密
restrict anonymous = 2 # 禁空会话
ntlm auth = no # 禁 NTLMv1
map to guest = Never # 禁 guest 回落
# hosts allow = 192.168.1.0/24 # IP 白名单
|
1
2
3
4
5
6
7
| # ===== 网络层(最关键)=====
# 445/139/137/138 【绝不出内网边界】,防火墙 deny
# 内网做微分段:只允许文件服务器接收 445,禁止工作站之间互连 445
# (这一条能挡住 90% 的勒索软件横向传播)
# 自查是否暴露
nmap -p 139,445 --script smb-protocols,smb-vuln-ms17-010 <你的公网IP>
|
与其他协议对比#
SMB vs NFS —— 核心对比#
| 维度 | SMB | NFS |
|---|
| 出身 | IBM/Microsoft(1983),DOS/Windows | Sun Microsystems(1984),Unix |
| 标准化 | 微软 MS-SMB2 开放规范(非 RFC) | IETF RFC(RFC 1813 / 7530 / 8881) |
| 端口 | TCP 445(旧 139 + UDP 137/138) | TCP 2049(v3 另需 111 + 动态端口) |
| 承载 | 自有消息格式,4 字节长度分帧 | ONC RPC + XDR |
| 状态 | 始终有状态(Session/Tree/File 三层) | v3 无状态 / v4 有状态 |
| 文件语义 | Windows:ACL、不区分大小写但保留大小写、ADS 备用数据流、打开的文件不可删 | POSIX:mode 位、区分大小写、硬链接、可删除已打开的文件 |
| 文件锁 | 强制锁(ShareAccess 冲突检测,语义严格) | v3 咨询锁(NLM,弱)/ v4 内置 |
| 缓存一致性 | 强(Oplock/Lease + 服务器主动 Break 回调) | 弱(close-to-open + 属性缓存超时) |
| 认证 | 内置 NTLM/Kerberos,开箱即用 | AUTH_SYS 自报 UID(极弱),强认证需额外部署 Kerberos |
| 加密 | SMB3 原生 AES-GCM,一条命令开启 | 需 sec=krb5p(部署复杂) |
| 权限模型 | NTFS ACL(细粒度) | POSIX mode / NFSv4 ACL |
| 性能特点 | 元数据操作与小文件更优(复合请求、Lease);大文件靠 Multichannel/RDMA | 大文件顺序 I/O 强;小文件弱 |
| 高可用 | 持久句柄 + 透明故障转移 + 多通道 | pNFS(v4.1)横向扩展 |
| 客户端 | Windows 原生;Linux 用 cifs-utils | Linux/Unix 原生;Windows 需装 NFS 客户端 |
| 主要风险 | 445 暴露 = 勒索软件入口;NTLM Relay | AUTH_SYS 可冒充任意 UID;no_root_squash 提权 |
| 选型 | 有 Windows 客户端 / 需要 ACL 与强锁语义 | 纯 Linux 环境 / K8s PV / HPC |
SMB 与其他文件访问方式#
| 维度 | SMB | NFS | FTP/SFTP | WebDAV | S3 |
|---|
| 挂载为本地盘 | ✅ | ✅ | 需 FUSE | ✅(性能差) | 需 s3fs |
| 部分读写 | ✅ | ✅ | ❌ | | Range |
| 文件锁 | ✅ 强 | 弱 | ❌ | | ❌ |
| 内置加密 | ✅ SMB3 | ❌ 需 Kerberos | ✅ SFTP | ✅ HTTPS | ✅ HTTPS |
| 广域网友好 | ❌(QUIC 除外) | ❌ | ✅ | ✅ | ✅ |
| 打印共享 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 典型场景 | Windows 办公共享 | Linux 集群 | 文件分发 | 跨平台协作 | 云存储 |
速查表 / 常见面试题#
端口 / 关键值速查#
| 项 | 值 |
|---|
| SMB Direct Hosting | TCP 445 |
| SMB over NetBIOS | TCP 139 |
| NetBIOS 名称服务 | UDP 137 |
| NetBIOS 数据报 | UDP 138 |
| SMB over QUIC | UDP 443 |
| SMB1 魔数 | 0xFF534D42(\xFFSMB) |
| SMB2/3 魔数 | 0xFE534D42(\xFESMB) |
| SMB3 加密报文魔数 | 0xFD534D42 |
| SMB2 头部长度 | 64 字节(SMB1 为 32) |
| 方言编号 | 2.0.2=0x0202 / 2.1=0x0210 / 3.0=0x0300 / 3.0.2=0x0302 / 3.1.1=0x0311 |
| 默认隐藏共享 | C$、ADMIN$、IPC$ |
常见 NTSTATUS 速查#
| 值 | 名称 | 一句话 |
|---|
0x00000000 | SUCCESS | 成功 |
0xC0000016 | MORE_PROCESSING_REQUIRED | NTLM 多轮中间态,不是错误 |
0xC000006D | LOGON_FAILURE | 账号或密码错 |
0xC0000022 | ACCESS_DENIED | 权限不足(分共享级/NTFS 级) |
0xC00000CC | BAD_NETWORK_NAME | 共享名不存在 |
0xC0000043 | SHARING_VIOLATION | 文件被占用 |
0xC0000034 | OBJECT_NAME_NOT_FOUND | 文件不存在 |
0xC0000203 | USER_SESSION_DELETED | 会话失效需重认证 |
0xC00000BB | NOT_SUPPORTED | 版本/特性不支持 |
一行命令速查#
1
2
3
4
5
6
7
| smbclient -L //HOST -N # 列共享(匿名)
smbclient //HOST/share -U 'DOM\user' # 交互访问
smbclient -L //HOST -N -m SMB1 # 探测是否还开着 SMB1
mount -t cifs //HOST/share /mnt -o credentials=/root/.cred,vers=3.1.1,seal
smbstatus # Samba:当前连接与锁
testparm # Samba:校验配置
nmap -p445 --script smb-protocols,smb-vuln-ms17-010 HOST
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| Get-SmbConnection | ft ServerName,ShareName,Dialect,Encrypted # 看协商版本 Get-SmbOpenFile # 谁开着文件
Get-SmbShareAccess -Name 'share' # 共享级权限
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force # 禁 SMB1 ```
### 常见面试题
**Q1:SMB1 和 SMB2 的区别?为什么必须禁用 SMB1?**
A:SMB2 是**彻底重写**而非小改:命令从 100+ 精简到 19 个、头部从 32 字节变 64 字节、引入 Credit 流控和复合请求、文件 ID 扩展到 128 位、单次 I/O 从 64KB 提升到 8MB。必须禁用 SMB1 的原因:① **无强制签名**,易被中间人篡改;② 认证机制弱(LM/NTLMv1);③ **EternalBlue(MS17-010)**等严重漏洞是 WannaCry/NotPetya 的传播途径;④ 性能极差(每个操作一次 RTT);⑤ 微软已正式宣布弃用,Windows 10/11 默认不安装。
**Q2:445 和 139 端口有什么区别?**
A:**139** 是 SMB over NetBIOS over TCP(NBT),需要配合 UDP 137(名称服务)和 138(数据报),是 Windows 2000 之前的方式;**445** 是 Direct Hosting,SMB 直接跑在 TCP 上,名称解析交给 DNS。现代环境应**只用 445,彻底关闭 137/138/139** —— NBT-NS 广播是内网 Responder 投毒攻击的主要入口。有意思的是 445 报文前仍保留 4 字节长度前缀,这是从 NBSS 头继承的分帧机制。
**Q3:Oplock 和 Lease 有什么区别?**
A:两者都是让客户端安全缓存文件的机制,服务器在冲突时主动回调打断。**Oplock**(SMB1/2.0)只有 Level II / Exclusive / Batch 三个粗粒度级别,且**绑定"打开实例"** —— 同一台机器上第二个进程打开同一文件就会打破 Oplock,缓存失效。**Lease**(SMB 2.1+)把权限拆成 **R/W/H 三个独立位**(读缓存/写缓存/句柄缓存),且用 **LeaseKey 绑定"客户端+文件"**,同一客户端的多个进程共享租约**互不打断**。这在真实场景(如 Office 打开文档、编译器反复读头文件)中性能差异巨大。
**Q4:SMB3.1.1 的预认证完整性(Pre-Auth Integrity)解决什么问题?**
A:解决**降级攻击**。SMB3.0 之前,中间人可以篡改 NEGOTIATE 报文,把方言列表改成只剩 SMB1 或去掉加密能力,迫使双方用弱协议通信,而这个篡改无法被检测(因为签名密钥是认证后才有的)。3.1.1 让双方**从第一个 NEGOTIATE 报文开始累积计算 SHA-512 哈希链**,这个哈希参与派生会话密钥。中间人一旦篡改任何握手报文,两端算出的哈希不同 → 密钥不同 → 签名校验失败 → 连接中断。
**Q5:SMB 的两层权限是什么?怎么定位是哪一层出问题?**
A:**共享级权限(Share Permissions)** 和 **NTFS/POSIX 文件系统权限**,最终权限取**交集**(更严格者生效)。抓包定位法:`TREE_CONNECT` 就返回 `ACCESS_DENIED` → 共享级问题;`TREE_CONNECT` 成功但 `CREATE` 返回 `ACCESS_DENIED` → NTFS/POSIX 问题。Windows 用 `Get-SmbShareAccess` 和 `Get-Acl` 分别查;Linux/Samba 还要额外检查 **SELinux 上下文**(`samba_share_t`),这是最常见的隐形杀手。
**Q6:`IPC$` 是什么?为什么它是安全重点?**
A:`IPC$` 是每台 Windows 上的隐藏共享,共享类型是 `PIPE`,承载**命名管道**。大量 Windows 远程管理协议实际是 **MSRPC over SMB Named Pipe**:`\svcctl`(服务控制,**PsExec 横向移动的原理**)、`\samr`(枚举用户)、`\winreg`(远程注册表)、`\netlogon`(**Zerologon 攻击面**)。这意味着**仅仅关闭文件共享是不够的** —— 只要 445 开着且 `IPC$` 可访问,攻击者就能做大量事情。老系统的**空会话(Null Session)**还能匿名枚举用户列表。
**Q7:SMB 和 NFS 怎么选?**
A:看客户端 OS 和文件语义需求。**SMB**:Windows 原生支持、NTFS ACL 细粒度权限、**强制锁语义严格**(ShareAccess 冲突检测)、缓存一致性强(Lease 回调)、**SMB3 内置 AES 加密和 Kerberos 开箱即用**。**NFS**:POSIX 语义原生(mode 位、硬链接、区分大小写、可删除已打开文件)、Linux 内核态实现、大文件顺序 I/O 强、K8s 生态支持好。**有 Windows 客户端就选 SMB,纯 Linux 就选 NFS**。安全性上 SMB3 明显优于默认配置的 NFS(AUTH_SYS 形同虚设)。
**Q8:什么是 SMB Multichannel?**
A:SMB3.0 的特性——**一个 SMB 会话可以同时使用多条 TCP 连接**(跨多张网卡,或在支持 RSS 的单网卡上开多条连接)。客户端通过 `FSCTL_QUERY_NETWORK_INTERFACE_INFO` 发现服务器的网卡列表,然后建立多条通道。收益有三:① **带宽聚合**(双万兆口可跑 20Gbps);② **CPU 多核并行**(单条 TCP 受限于单核);③ **链路故障自动切换**(无需网卡组队)。用 `Get-SmbMultichannelConnection` 查看是否生效。
**Q9:为什么 SMB 传大量小文件很慢?**
A:每个文件都需要 `CREATE` → `QUERY_INFO` → `READ` → `CLOSE` 多次交互。虽然 SMB2 的**复合请求**能把这些打包进一个 TCP 报文(比 SMB1 好很多),但文件数量本身带来的开销无法消除——1 万个小文件就是至少 1 万次往返。**这不是调参能解决的**。缓解手段:打包成压缩文件传输、使用 Lease 句柄缓存(H 位)、减少单目录文件数、高延迟链路考虑用 robocopy 的多线程模式(`/MT:32`)。
**Q10:NTLM Relay 攻击是怎么回事?SMB 签名如何防御?**
A:NTLM 是**挑战-响应**认证,但**不绑定通信信道**。攻击者诱使受害者向自己发起 SMB 连接(如 UNC 路径注入、LLMNR/NBT-NS 投毒),然后把收到的 NTLM 认证消息**原样转发**到真正的目标服务器,从而以受害者身份登录——攻击者全程不需要知道密码。**SMB 签名**的防御原理是:签名密钥由**会话密钥**派生,而会话密钥与具体的认证会话绑定,中继者拿不到会话密钥就无法为后续报文生成正确签名,连接会被拒绝。因此**强制 SMB 签名 + 禁用 NTLM(改用 Kerberos)+ 关闭 LLMNR/NBT-NS** 是标准防御组合。
|