暗色模式

Samba 文件共享:从 smb.conf 配置到 SMB 客户端挂载

技术教程
2026-09-07
6
0
本文要点
  • Samba 是 SMB/CIFS 协议的开源实现,专治「Linux 服务器 + Windows/macOS 客户端」混编环境;与面向 Linux 之间的 NFS 互补(NFS 已另文实测,本文实测对象是 Samba)
  • 一条命令装齐三件套:apt-get install -y samba smbclient cifs-utils——服务端 smbd、命令行客户端 smbclient、内核挂载工具 mount.cifs(实测 Ubuntu 24.04.4 上是 Samba 4.19.5、cifs-utils 2.7.0)
  • SMB 账号是独立体系:useradd 只建系统账号,smbpasswd -a 单独设置 SMB 密码;给共享账号配 /usr/sbin/nologin 登录 shell 可防止其 SSH 登录服务器
  • 一个共享 = 服务层 + 文件系统层双重权限:read only/valid users/guest ok 只决定 Samba 放不放行,目录的 Linux 属主权限不放开,写入照样报 Permission denied(本文实测踩中:共享目录属主是 root,SMB 用户写入被拒,chown 给共享用户后立即成功)
  • 匿名访客默认映射 map to guest = Bad User:guest 只读共享用 smbclient //主机/共享 -N 一条命令即可验证,写入会被服务端以 NT_STATUS_ACCESS_DENIED 拒绝
  • Linux 客户端挂载用 mount -t cifs //127.0.0.1/docs /mnt/smb -o username=...,password=...,vers=3.0vers 显式指定协议版本是因为 SMB1 因安全原因默认关闭,务必用 SMB3+;服务器侧真实属主与客户端看到的不一致是 uid 映射所致,属正常现象
  • 全部命令在 Ubuntu 24.04.4 云服务器(Samba 4.19.5)上真实执行,截图即真实输出;演示账号、共享目录与挂载点在演示结束后已清理

Samba 文件共享:从 smb.conf 配置到 SMB 客户端挂载

前一篇《NFS 网络文件共享》解决的场景是 Linux 与 Linux 之间共享目录。但真实办公室里往往是一台 Linux 服务器 + 一堆 Windows / macOS 桌面——要让它们像访问网上邻居一样读写服务器目录,标准答案是 Samba:SMB/CIFS 协议的开源实现,Linux 上服务端的事实标准,Windows 甚至自带同名内核客户端,零额外软件就能直连。

本文在一台 Ubuntu 24.04.4 云服务器(2 vCPU / 1.8G 内存,内核 6.8.0-136-generic)上完整走一遍 Samba 日常主线:安装 → 建共享目录与 SMB 账号 → 编写 smb.conf → 匿名只读与账号读写双向验证 → Linux 内核挂载并真实踩一次权限坑。全部命令实测执行,截图即真实输出。

安装:服务端与客户端工具一次装齐

Ubuntu 官方源里把三件套打成了一个安装命令:服务端 smbd、命令行客户端 smbclient、内核挂载工具 cifs-utils。以下命令需要 root 权限(本文演示环境以 root 操作,普通用户自行加 sudo):

apt-get install -y samba smbclient cifs-utils

安装 samba、smbclient、cifs-utils

输出很长,上图截取了「配置阶段」的结尾部分。三条关键信息值得注意:

  • 装上的实际版本是 Samba 4.19.52:4.19.5+dfsg-4ubuntu9.7)与 cifs-utils 2.7.0
  • 安装过程自动创建了 systemd 符号链接:smbd.servicenmbd.service 都被链接到 multi-user.target.wants——也就是说 Samba 安装完即注册为开机自启服务;
  • Ubuntu 的 samba 包默认把服务拆成 smbd(文件共享)与 nmbd(NetBIOS 名称服务)。现代 SMB 客户端已不依赖 NetBIOS,本文只关心 smbd,需要时单独操作它即可。

确认版本:

smbd --version
Version 4.19.5-Ubuntu

准备共享目录与 SMB 账号

先建一个共享目录并放入两个演示文件——模拟「团队文档」场景:

mkdir -p /srv/share/docs
printf '季度销售报表 v1.2\n' > /srv/share/docs/sales-2026-q3.md && printf '产品路线图讨论纪要\n' > /srv/share/docs/roadmap-notes.md
ls -l /srv/share/docs
total 8
-rw-r--r-- 1 root root 28 Sep  7 05:07 roadmap-notes.md
-rw-r--r-- 1 root root 24 Sep  7 05:07 sales-2026-q3.md

接下来创建 SMB 账号。这里要强调一个新手最容易绕晕的点:SMB 密码与系统登录密码是两套独立体系useradd 只是让系统里存在这个用户(Samba 要求账号先存在于系统),smbpasswd -a 才设置 Samba 自己的密码。给共享账号配上 /usr/sbin/nologin 登录 shell,还能顺手杜绝它 SSH 登录服务器:

useradd -M -s /usr/sbin/nologin smbuser
smbpasswd -a smbuser -s
Added user smbuser.

-s 表示从标准输入读取密码(可脚本化);交互执行时去掉它即可,会提示输入两次。演示环境用的密码是 Demo#Smb2026——仅限演示,真实环境请用强密码并定期轮换。

编写 smb.conf:只读公共 + 账号读写两个共享

Ubuntu 自带的 /etc/samba/smb.conf 是完整模板,先备份再往末尾追加我们的共享定义,是最稳妥的改法:

cp /etc/samba/smb.conf /etc/samba/smb.conf.bak
cat >> /etc/samba/smb.conf <<'SMBCONF'

[docs]
   comment = 团队共享目录
   path = /srv/share/docs
   browseable = yes
   read only = no
   valid users = smbuser
   create mask = 0644
   directory mask = 0755

[public]
   comment = 只读公共目录
   path = /srv/share/docs
   browseable = yes
   read only = yes
   guest ok = yes
SMBCONF

这里刻意写了两个共享指向同一目录,用来对比 Samba 的三种访问控制手段:

  • [docs]账号读写共享read only = no 放行写入,但 valid users = smbuser 把访问者限定为指定账号,其余人连登录都过不了;
  • [public]访客只读共享guest ok = yes 允许匿名访问,read only = yes 禁止写入;
  • create mask / directory mask:新文件/新目录在服务器端落地时的权限掩码,对服务层放行之外做第二道约束(下文会看到真正的第二道约束其实是文件系统权限)。

配置写完后先用 testparm 校验语法。它会重新加载配置并输出解析结果,是排查共享问题的第一步:

testparm -s

testparm 校验配置输出

注意几个输出细节:

  • 全局段里 map to guest = Bad User——Ubuntu 默认值,含义是「用户名对不上时映射为匿名访客」,这正是 guest ok 能工作的前提;
  • [docs] 解析出 read only = Novalid users = smbuser[public] 解析出 guest ok = Yes,与我们写的一致;
  • 结尾的 Load smb config files ... + Loaded services file OK. 就是「配置无错」的官方宣告。

校验通过后重启服务让配置生效,并顺手确认状态:

systemctl restart smbd && systemctl is-active smbd
active

验证一:匿名访客只能读

先用 smbclient 扮演「匿名访客」访问 [public]-N 表示不发账号密码,直接以 guest 身份尝试:

smbclient //127.0.0.1/public -N -c 'ls'
  .                                   D        0  Mon Sep  7 05:07:12 2026
  ..                                  D        0  Mon Sep  7 05:07:12 2026
  roadmap-notes.md                    N       28  Mon Sep  7 05:07:12 2026
  sales-2026-q3.md                    N       24  Mon Sep  7 05:07:12 2026

        40972748 blocks of size 1024. 18731608 blocks available

目录列表拿到了,两个文件都可见。那 guest 能写吗?试试往共享里传一个文件(put 的语法是 put 本地文件 远端文件名):

smbclient //127.0.0.1/public -N -c 'put /etc/hostname hostname.txt'
NT_STATUS_ACCESS_DENIED opening remote file \hostname.txt

NT_STATUS_ACCESS_DENIED——被服务端明确拒绝。read only = yes 在 Samba 层就把写操作拦死了,这正是「公共只读」该有的行为。

验证二:账号挂载与写入(一次真实的权限坑)

客服用 smbclient 适合临时操作;要像本地目录一样持续使用,得用 Linux 内核自带的 CIFS 客户端挂载。先建挂载点,再用 smbuser 的凭据挂载 [docs]

mkdir -p /mnt/smb
mount -t cifs //127.0.0.1/docs /mnt/smb -o 'username=smbuser,password=Demo#Smb2026,vers=3.0'

几点说明:

  • vers=3.0 显式要求 SMB 3.0 协议。SMB1(vers=1.0)因勒索软件风波被现代 Samba 默认禁用,老教程里不带 vers 的写法在 4.19 上会协商失败;显式声明也能避免将来静默降级到弱协议;
  • 演示环境用 127.0.0.1 回环地址,因此不需要开防火墙;真实跨机器访问时,除本机防火墙外,还要记得在云厂商安全组放行 TCP 445(本文的服务器由安全组隔离,445 未对公网开放);
  • 凭据明文出现在命令行里只适合演示与脚本初排,生产建议改用 credentials 文件或 Kerberos。

挂载本身没有输出——成功就是静默的。往里写个文件试试:

echo '由 CIFS 客户端写入的行' > /mnt/smb/from-cifs.txt
bash: line 1: /mnt/smb/from-cifs.txt: Permission denied

写入被拒了!read only = novalid users = smbuser 都配对了,为什么还报 Permission denied?回头看第一步的 ls -l:目录属主是 root,权限 drwxr-xr-x——root 之外的用户对这个目录只有读和执行的份。Samba 的 read only 只是服务层的放行开关,最终能否写入还要过文件系统层:SMB 会话里的 smbuser,映射到服务器上就是 smbuser 这个系统用户,它对 root 拥有的目录没有写权限。

修复方法就是把目录及其内容交给共享用户:

chown -R smbuser:smbuser /srv/share/docs

再执行刚才失败的写入,这次换成「写入 + 读回」一条链,一次验证读写两个方向:

echo '由 CIFS 客户端写入的行' > /mnt/smb/from-cifs.txt && cat /mnt/smb/from-cifs.txt

权限修正后写入成功

写入成功且内容读回一致。到服务器侧看真实属主,文件已经归 smbuser 所有:

ls -l /srv/share/docs
total 12
-rw-r--r-- 1 smbuser smbuser 31 Sep  7 05:07 from-cifs.txt
-rw-r--r-- 1 smbuser smbuser 28 Sep  7 05:07 roadmap-notes.md
-rw-r--r-- 1 smbuser smbuser 24 Sep  7 05:07 sales-2026-q3.md

而从挂载点看,同样的文件显示属主却是 root、权限 rwxr-xr-x

ls -l /mnt/smb
total 9
-rwxr-xr-x 1 root root 31 Sep  7 05:07 from-cifs.txt
-rwxr-xr-x 1 root root 28 Sep  7 05:07 roadmap-notes.md
-rwxr-xr-x 1 root root 24 Sep  7 05:07 sales-2026-q3.md

两边不一致不是错误,而是 CIFS 客户端的 uid/gid 映射行为:挂载时没指定 uid/gid,客户端就把远程文件都映射成本地挂载者(root);file_mode/dir_mode 未指定时默认按 0755 呈现。想让客户端侧也显示真实属主,挂载时加上 uid=1001,gid=1001(视 smbuser 在客户机上的 uid 而定)即可。排查共享权限问题时务必记住:服务器侧 ls 才是权威

Windows 与 macOS 客户端怎么连

同一套服务端,桌面端几乎零配置:

  • Windows:资源管理器地址栏直接输入 \\服务器IP\docs,弹窗时填 smbuser 和 SMB 密码;或命令行 net use Z: \\服务器IP\docs /user:smbuser 映射成盘符(会提示输入密码)。Windows 自带 SMB 客户端,无需安装任何东西;
  • macOS:访达 →「前往」→「连接服务器」,输入 smb://服务器IP/docs,同样用 smbuser 登录即可挂载成卷。

桌面端能读不能写时,优先检查的仍是本文踩过的那条链:共享层 read onlyvalid users/guest ok → 文件系统属主权限。

小结

回顾整条链路,Samba 的日常运维其实就三件事:装对包、写对配置、记住双重权限。配置语法用 testparm 兜底,服务状态用 systemctl 确认,行为验证用 smbclient(guest 只读场景)或 mount -t cifs(账号读写场景)分别打一遍,基本不会有大问题。需要把 CIFS 挂载固化成开机自动挂载时,可参考《Linux 磁盘挂载》的 fstab 写法,并把密码挪进权限 600 的 credentials 文件。本文演示用的账号、共享目录与挂载点,在验证结束后已全部清理,服务器保持干净状态。

发表评论

暂无评论,快来抢沙发吧!