Samba 文件共享服务
本文合并自:05-Samba服务.md、11-Samba服务.md、1-13-Samba服务部署.md
适用环境:CentOS/RHEL 5/6(Samba 3.x)与 CentOS/RHEL 7(Samba 4.x)。文中凡涉及两个版本操作差异之处,均并列给出并标注适用版本。
一、Samba 概述与原理
1.1 什么是 Samba
Samba 是一套基于 SMB(Server Messages Block,信息服务块)协议 的开源网络文件共享服务,主要用于在 Windows 与 UNIX/Linux 之间共享文件、打印机等资源。
Samba 最初由 DEC 开始开发,用于在不同的 Unix 机器间进行资源共享,早期采用 UDP 协议。后来基于 TCP 重新开发后,效率有了很大提高,它使用的协议是 SMB。微软不愿意交 License 费,在 Windows 系统中对该协议重新进行了实现。既然 Samba 和 Windows 中的「网络邻居」都使用 SMB 协议,那么 Samba 自然主要用于在 Windows 和 Unix 之间共享资源,资源包括文件、打印机等等。
| 项目 | 说明 |
|---|---|
| 协议 | SMB(历史上基于 UDP,现代版本基于 TCP) |
| 主要用途 | Windows 与 Linux/Unix 之间共享文件、打印机 |
| 与 NFS 对比 | Samba 配置更灵活,NFS 配置更简单;NFS 更适合纯 Unix/Linux 环境 |
1.2 Samba 服务的特点
- 支持更详细的访问控制(可对同一目录下的不同用户设置不同权限);
- 可跨平台共享文件(Linux↔Windows、Linux↔Linux);
- 对初级用户友好,Windows 端可直接「映射网络驱动器」使用。
典型使用场景:
- 办公网内为 Windows 桌面用户提供部门文件服务器;
- Linux 服务器把日志、软件包目录共享给 Windows 运维终端;
- 多用户协作目录,要求「能读别人的、只能删自己的」这类精细权限;
- 网络打印机共享。
1.3 SMB/CIFS 协议与版本演进
SMB 协议在发展过程中出现了 CIFS(Common Internet File System)这一名称,它本质上是 SMB 1.0 的一个方言/扩展,Linux 挂载时使用的文件系统类型名 cifs 即源自此。
| 协议版本 | 说明与适用性 |
|---|---|
| SMB1 / CIFS | 最早的版本,Windows XP / Windows Server 2003 及部分老旧设备(老式打印机、NAS、扫描仪)使用。存在严重安全问题(明文/弱认证、无消息签名强制、易受中间人与 WannaCry 类蠕虫攻击),现代系统默认禁用,应尽量不再启用 |
| SMB2(2.0/2.1) | Windows Vista / 7 / Server 2008 起引入,减少了命令往返次数,性能与稳定性大幅提升 |
| SMB3(3.0/3.02/3.1.1) | Windows 8 / Server 2012 及以后,支持传输加密、多通道(Multichannel)、持久句柄、SMB Direct 等特性,是目前推荐使用的版本 |
在 Samba 中通过 [global] 段的 min protocol / max protocol 控制可协商的协议版本;客户端挂载时通过 -o vers= 指定版本。
[global]
# 禁用不安全的 SMB1,最低要求 SMB2
min protocol = SMB2
max protocol = SMB3
注意:禁用 SMB1 后,Windows XP 等老客户端与部分老旧硬件设备将无法连接(详见排错清单)。
1.4 NetBIOS 名称解析与 WINS
Windows 网络中主机之间除了使用 IP,还使用 NetBIOS 名称(长度不超过 15 个字符的计算机名)互相标识。NetBIOS 名称解析有以下几种途径:
- 广播:在同一广播域内发送 NetBIOS 名称查询广播包(UDP 137);
lmhosts静态映射文件:Samba 端为/etc/samba/lmhosts,写法类似/etc/hosts;- WINS(Windows Internet Name Service)服务器:集中注册和解析 NetBIOS 名称,可跨网段解析。Samba 可以作为 WINS 服务器或 WINS 客户端:
[global]
# 让 Samba 自身充当 WINS 服务器
wins support = yes
# 或者作为客户端向指定 WINS 服务器注册与查询(两者不可同时启用)
# wins server = 192.168.0.10
# 名称解析顺序
name resolve order = lmhosts wins bcast host
NetBIOS 名称解析由 nmbd 进程负责。如果客户端只通过 IP 地址访问共享,则名称解析并非必需。
1.5 Samba 使用的端口
| 端口 | 协议 | 用途 | 对应进程 |
|---|---|---|---|
| 137 | UDP | NetBIOS 名称服务(名称注册与解析) | nmbd |
| 138 | UDP | NetBIOS 数据报服务(浏览列表、工作组通告) | nmbd |
| 139 | TCP | NetBIOS Session Service,SMB over NetBIOS(旧方式) | smbd |
| 445 | TCP | SMB over TCP(直接承载,现代方式) | smbd |
RHEL 6 默认环境下实际只监听 TCP 139、445(UDP 137/138 由 nmbd 在启动后监听,若未启动 nmb 则不监听)。
验证监听状态:
netstat -ntlup | grep bd
# tcp 0 0 :::139 :::* LISTEN 4507/smbd
# tcp 0 0 :::445 :::* LISTEN 4507/smbd
1.6 Samba 的三个核心进程
| 守护进程 | 职责 | 相关端口 |
|---|---|---|
smbd |
核心进程。管理共享目录、文件读写与打印服务,负责用户认证、权限判定、SMB 会话处理 | TCP 139、445 |
nmbd |
管理工作组(workgroup)、NetBIOS 名称解析与浏览列表(网上邻居中能否被自动发现) | UDP 137、138 |
winbindd |
与 Windows 域控制器(NT 域 / AD 域)交互,把域用户和域组映射为 Linux 本地的 UID/GID,实现统一身份认证。仅在加入域环境时需要 |
关于
smb与nmb服务单元:smb是提供文件共享的主服务,nmb(nmbd)只负责 NetBIOS 名称解析与「网上邻居」浏览列表。若客户端通过 IP 地址访问(如smbclient -L //192.168.0.183),仅启动smb即可满足需求,日常调试常简写为systemctl restart smb;只有需要通过 NetBIOS 名称访问或在 Windows 网络中被自动发现时,才必须同时启动nmb。
1.7 Samba 与 NFS、FTP 适用场景对比
| 特性 | Samba | NFS |
|---|---|---|
| 开发方 | DEC 发起 | Sun 开发 |
| 主要协议 | SMB/CIFS | NFS |
| 最佳场景 | Windows 与 Linux 跨平台共享 | Unix/Linux 之间共享 |
| 配置复杂度 | 较高,参数灵活 | 较低,配置简单 |
| 典型效率 | 与 NFS 接近,通常 NFS 略高 | 通常略高 |
| 权限模型 | 有独立的用户密码库,可做同目录多用户差异化权限 | 依赖客户端 UID/GID 映射,权限控制较粗 |
三种共享服务的横向对比:
| 对比项 | FTP | Samba | NFS |
|---|---|---|---|
| 跨公网 | 可以直接跨公网 | 不能直接跨公网,需借助 VPN | 一般用于内网 |
| 权限控制 | 较弱,不适合多用户在同一目录做不同权限 | 权限控制精细,适合同目录多用户不同权限 | Linux 到 Linux |
| 跨平台 | 跨平台 | 跨平台(Linux↔Windows、Linux↔Linux) | Linux↔Linux |
| 客户端易用性 | 需 FTP 客户端软件 | 可在 Windows 中映射网络驱动器,对初级用户友好 | Linux 挂载 |
NFS 的配置主要是编辑 /etc/exports 文件,然后运行 exportfs -arv 共享出来,现在 NFS 已经成为 UNIX/Linux 上的标配。从效率来看 NFS 稍微高一些,但差别不是太大;从配置来看 Samba 比较复杂,但复杂有复杂的道理,它让我们能够更灵活地配置。
1.8 客户端访问控制的总流程
无论什么服务,客户端访问一般都要依次经过以下几道关卡,排错时应按此顺序逐层检查:
客户端程序
|
iptables / firewalld(防火墙)
|
pam(控制是否可登录)
|
selinux(程序域能否访问文件/目录类型)
|
服务参数是否允许(smb.conf)
|
系统权限 rwx(含 ACL、粘滞位)
|
服务程序
常用服务的匿名用户身份:
| 服务 | 匿名用户 |
|---|---|
| NFS | nfsnobody |
| FTP | ftp、anonymous |
| Samba | nobody |
二、安装与主配置文件详解
2.1 安装软件包
# 安装 Samba 服务端及常用组件
sudo yum install samba samba-common -y
# 安装 Samba 客户端(用于测试或挂载其他共享)
sudo yum install samba-client -y
也可以一次性安装全部相关包:
yum install samba* -y
RHEL 6.4 以上版本 ISO 自带两个版本的 samba,
yum install samba*可能报冲突,可改用yum install samba-*。
各包的作用:
| 软件包 | 作用 |
|---|---|
samba |
服务端主程序,提供 smbd、nmbd |
samba-common |
服务端与客户端公用的配置文件与工具(如 testparm) |
samba-client |
客户端工具,提供 smbclient、smbtar 等 |
samba-winbind、samba-winbind-clients |
winbindd 及其客户端,用于对接 NT/AD 域 |
cifs-utils |
提供 mount.cifs,Linux 挂载 SMB 共享的必需包 |
查看已安装包:
rpm -qa | grep samba
# samba-winbind-3.5.10-125.el6.x86_64
# samba-common-3.5.10-125.el6.x86_64
# samba-winbind-clients-3.5.10-125.el6.x86_64
# samba-client-3.5.10-125.el6.x86_64
# samba-3.5.10-125.el6.x86_64
Samba 完整详细的文档可参考 man 文档:
man smb.conf
# 或 man 5 smb.conf
2.2 目录与文件结构
| 路径 | 说明 |
|---|---|
/etc/samba/smb.conf |
主配置文件 |
/etc/samba/smbusers |
Samba 用户名与 Linux 用户名的映射表(配合 username map) |
/etc/samba/smbpasswd |
早期 smbpasswd 后端的密码文件(使用 tdbsam 后端时不再使用) |
/etc/samba/lmhosts |
NetBIOS 名称到 IP 的静态映射文件 |
/var/lib/samba/ |
运行期数据库目录,passdb.tdb(账号库)、secrets.tdb(机器账号与域密钥)、browse.dat 等 |
/var/log/samba/ |
日志目录,log.smbd、log.nmbd、log.<客户端名> |
/var/spool/samba/ |
打印共享的假脱机目录 |
/usr/bin/smbclient、smbpasswd、pdbedit、testparm、smbstatus |
常用命令 |
编辑主配置文件:
sudo vim /etc/samba/smb.conf
2.3 smb.conf 的结构
Samba 配置文件由多个「段(section)」组成,段名用方括号括起。[global] 为全局配置,[homes]、[printers] 是两个特殊的内置共享段,其余为自定义共享段:
[global] # 表示这是影响全局的配置
workgroup = MYGROUP # 工作组
server string = Samba Server Version %v # 服务器描述
log file = /var/log/samba/log.%m
max log size = 50
security = user # 非常重要的参数:user 代表客户端必须提供用户名和密码(匿名除外)
# 值为 share 时不需要密码,下面的配置要做相应改变
passdb backend = tdbsam # 使用本地 .tdb 文件保存账号密码
load printers = yes # 是否加载打印机
cups options = raw # 打印机类型
[homes] # 用户家目录共享(特殊段)
comment = Home Directories
browseable = no
writable = yes
[printers] # 打印机共享(特殊段)
comment = All Printers
path = /var/spool/samba
browseable = no
guest ok = no
writable = no
printable = yes
[software] # 自定义共享段:只读共享示例
comment = Shared software # 自定义描述
path = /external/software # 共享目录
guest ok = yes # 是否允许匿名访问
browseable = yes # 是否出现在查询列表中
writeable = no # 是否可写
[upload] # 自定义共享段:可写共享示例
comment = Upload
path = /opt/upload
guest ok = no
browseable = yes
writeable = yes
valid users = u1,u2,+g1 # 允许访问的用户和组
write list = u1 # 读写列表
read list = u2,+g1 # 只读列表
create mode = 0344 # 控制新建文件的权限
force create mode = 0344 # 控制新建文件的权限
directory mode = 0777 # 控制新建目录的权限
force directory mode = 0777 # 控制新建目录的权限
hosts deny = all # 禁止访问的客户端
hosts allow = 192.168.0.0/24 except 192.168.0.222 # 允许访问的客户端
部分资料中出现的
assdb backend = tdbsam是笔误,正确指令为passdb backend。
[homes] 段的含义:该段会在用户登录时自动把共享名变为对应用户的家目录。Samba 默认把每个系统用户的家目录共享出去,但前提是该用户已通过 smbpasswd -a 加入 Samba 账号库。若不希望用户访问自己的家目录,把 [homes] 段整体注释即可。
2.4 [global] 全局段常用参数逐项详解
| 参数 | 说明 |
|---|---|
workgroup |
Windows 工作组(或 NT 域)名称,需与客户端一致才便于在网上邻居中发现 |
server string |
服务器描述信息,%v 为 Samba 版本变量 |
netbios name |
本机在 Windows 网络中显示的 NetBIOS 名称(不超过 15 字符),默认取主机名的第一段 |
security |
安全(工作)模式,取值 user / share / server / domain / ads,详见 2.5 |
passdb backend |
用户密码数据库后端。tdbsam 表示使用本地 TDB 数据库文件 /var/lib/samba/passdb.tdb;历史上还有 smbpasswd(纯文本文件)与 ldapsam(LDAP) |
map to guest |
认证失败时如何降级为 guest。Never(默认,直接拒绝)、Bad User(用户名不存在则当作 guest,实现匿名共享的关键)、Bad Password(密码错误也当 guest,不安全)、Bad Uid |
guest account |
匿名访问时映射到的系统账号,默认 nobody |
hosts allow |
允许访问的客户端列表,可写网段、IP、主机名,支持 EXCEPT 排除 |
hosts deny |
拒绝访问的客户端列表 |
interfaces |
指定 Samba 监听的网络接口或网段,如 interfaces = lo eth0 192.168.0.0/24 |
bind interfaces only |
值为 yes 时仅在 interfaces 列出的接口上监听,用于把服务限制在内网口 |
log file |
日志文件路径,%m 代表客户端 NetBIOS 名,可为每个客户端生成单独日志 |
max log size |
单个日志文件最大大小(单位 KB),超过后轮转,0 表示不限制 |
log level |
日志级别 0~10,数字越大越详细,排错时可临时调到 3 |
smb ports |
smbd 监听的端口,默认 445 139 |
min protocol |
允许协商的最低协议版本,如 SMB2,用于禁用不安全的 SMB1 |
max protocol |
允许协商的最高协议版本,如 SMB3 |
unix charset |
Linux 服务器端使用的字符集,通常为 UTF-8 |
dos charset |
与老式 Windows/DOS 客户端交互使用的字符集,简体中文环境为 cp936(GBK),用于解决中文文件名乱码 |
display charset |
服务器端显示(如 smbclient 输出)使用的字符集 |
load printers |
是否自动加载 /etc/printcap 中的所有打印机为共享 |
printing |
打印系统类型,如 cups、lprng、bsd |
cups options |
CUPS 打印选项,raw 表示由客户端驱动生成打印数据,服务器不再处理 |
config file |
按变量加载附加配置文件,如 config file = /etc/samba/smb.conf.%U(%U 为登录用户名) |
include |
包含另一个配置文件,同样支持 %U、%m 等变量 |
wins support / wins server |
充当 WINS 服务器 / 指定 WINS 服务器(互斥) |
name resolve order |
NetBIOS 名称解析顺序,如 lmhosts wins bcast host |
username map |
用户名映射文件,通常为 /etc/samba/smbusers |
中文乱码的典型配置:
[global]
unix charset = UTF-8
dos charset = cp936
display charset = UTF-8
2.5 security 工作模式的演变
| 模式 | 说明 | 适用版本 |
|---|---|---|
share |
不需要用户名密码,匿名用户模式 | Samba 3.x(CentOS 5/6)可用;Samba 4.x 起已废弃,CentOS 7 中不再支持 |
user |
使用 Samba 自己的密码资料库(普通用户模式),需提供用户名和密码,最常用 | 全版本 |
server |
使用外部主机(另一台 SMB 服务器)的密码,用户信息存放在远程服务器 | Samba 3.x,已废弃 |
domain |
加入 NT 域,由域控制器认证 | 全版本 |
ads |
加入 Active Directory 域,使用 Kerberos 认证 | Samba 3.x 起 |
CentOS 7 / Samba 4 注意:
security = share与security = server已被移除。要实现匿名共享,应使用security = user搭配map to guest = Bad User,并在共享段设置guest ok = yes。
[global]
security = user
map to guest = Bad User # CentOS 7 实现匿名访问的关键
guest account = nobody
2.6 共享段常用参数逐项详解
| 参数 | 说明 |
|---|---|
comment |
共享的描述信息,客户端浏览时显示 |
path |
共享目录的本地绝对路径 |
browseable |
是否在共享(浏览)列表中可见。no 时共享仍可用,只是「隐藏」,知道共享名可直接访问 |
writable / writeable |
是否可写(与 read only 反义) |
read only |
是否只读(与 writable 反义) |
public |
是否允许匿名用户登录(与 guest ok 同义) |
guest ok |
是否允许匿名用户登录(与 public 同义) |
guest only |
只允许以 guest 身份访问该共享 |
valid users |
指定允许访问的用户/组白名单,组名前加 @ 或 +,如 valid users = u1,u2,@smb |
invalid users |
拒绝访问的用户/组黑名单,优先级高于 valid users |
write list |
具有写权限的用户/组列表(即使共享为 read only = yes,列表内用户仍可写) |
read list |
只有读权限的用户/组列表(与 write list 反义) |
admin users |
该列表内的用户在此共享中以 root 身份操作,可读写删除任何文件(权限极大,谨慎使用) |
create mask / create mode |
新建文件的权限掩码(上限),类似 umask 的作用方向相反,直接给出允许的权限位 |
force create mode |
强制新建文件必须具备的权限位(下限) |
directory mask / directory mode |
新建目录的权限掩码 |
force directory mode |
强制新建目录必须具备的权限位 |
force user |
强制所有访问该共享的用户以指定系统用户身份操作文件 |
force group |
强制所有新建文件的属组为指定组,常用于多用户组协作共享 |
available |
no 时该共享被临时禁用(配置保留但不生效) |
follow symlinks |
是否跟随共享目录内的符号链接,默认 yes |
wide links |
是否允许跟随指向共享目录之外的符号链接,默认 no(安全考虑) |
veto files |
完全隐藏且禁止访问的文件模式,以 / 分隔,如 veto files = /*.mp3/*.exe/ |
delete veto files |
删除目录时是否连同被 veto 的文件一起删除 |
hide files |
隐藏(但仍可访问)的文件模式,写法同 veto files |
hide dot files |
是否把以 . 开头的文件标记为隐藏,默认 yes |
inherit permissions |
新建文件/目录继承父目录的权限位,会覆盖 create mask 的效果 |
inherit acls |
新建对象继承父目录的 POSIX ACL |
printable |
该共享是否为打印队列共享(打印共享必须为 yes) |
hosts allow / hosts deny |
允许/拒绝访问的客户端地址,可写在共享段仅对该共享生效 |
max connections |
该共享允许的最大并发连接数 |
vfs objects |
加载 VFS 模块,如 recycle(回收站)、full_audit(审计) |
三对同义/反义参数(务必只写一个,避免冲突):
public与guest ok(同义);writable/writeable与read only(反义);write list与read list(反义)。
当反义/同义参数同时出现时,写在后面的参数生效:
[test]
comment = public for everyone
path = /test
browseable = yes
read only = yes
writable = yes # 写在后面,最终结果是可写
create mode 与 force create mode 的区别
两者名字相近但作用方向相反,容易混淆:
| 参数 | 性质 | 作用 |
|---|---|---|
create mode |
掩码(上限) | 客户端请求的权限与该值按位「与」运算,只能去掉多余权限,不会增加权限 |
force create mode |
强制置位(下限) | 与结果按位「或」运算,将指定的权限位强制打开,无论客户端是否请求 |
计算顺序为:最终权限 = (客户端请求权限 & create mode) | force create mode。
例如同时设置 create mode = 0400 与 force create mode = 0400,则新建文件的权限被锁定为 0400(仅属主可读):掩码把组和其他人的权限全部去掉,强制位再保证属主的读权限一定存在。若只写 create mode = 0400,当客户端本身请求 0000 时结果仍是 0000;若只写 force create mode = 0400,客户端请求的其他权限位仍会被保留。directory mode 与 force directory mode 对目录的作用方式完全相同。
权限默认值机制小结:
| 机制 | 文件默认权限 | 目录默认权限 |
|---|---|---|
| 系统 umask | 666 - umask |
777 - umask |
vsftpd anon_umask / local_umask |
666 - umask |
777 - umask |
Samba create mask / directory mask |
直接定义为所设值 | 直接定义为所设值 |
注意:无论哪种机制,最终权限不一定完全等于配置值(还受父目录、
inherit permissions、客户端请求影响),以实际测试结果为准。Samba 默认上传文件权限为0744,新建目录为0755。
2.7 访问控制(hosts allow / hosts deny)
访问控制指令可写在 [global] 全局段(对所有共享生效),也可写在单独共享段(仅对该共享生效)。
# 拒绝 10.0.0 网段
hosts deny = 10.0.0.
# 拒绝 10.0.0 网段,但允许 10.0.0.35(allow 优先于 deny)
hosts deny = 10.0.0.
hosts allow = 10.0.0.35
# 拒绝所有,但允许 10.0.0 网段,其中 10.0.0.45 除外
hosts deny = all
hosts allow = 10.0.0. EXCEPT 10.0.0.45
# 也可使用掩码写法
hosts allow = 192.168.0.0/255.255.255.0 except 192.168.0.222
hosts allow = 192.168.0.0/24 except 192.168.0.222
规则:
hosts allow的优先级高于hosts deny;EXCEPT(或小写except)用于在允许范围内排除个别地址。
2.8 testparm 语法检查
修改配置文件后,务必先用 testparm 检查语法,再重载服务:
sudo testparm
常用形式:
testparm # 检查语法并交互式显示解析后的配置
testparm -s # 直接输出解析结果,不等待回车
testparm -v # 显示包括默认值在内的全部参数
testparm -s /etc/samba/smb.conf.u1 # 检查指定的配置文件
输出中 Loaded services file OK. 表示语法无误。修改 smb.conf 前建议先备份:
cp /etc/samba/smb.conf /etc/samba/smb.conf.bak
三、用户管理与共享实战
3.1 Samba 账号体系与系统账号的关系
在 security = user 模式下,Samba 用户必须同时满足以下两个条件:
- 必须是服务器上的 系统用户(先用
useradd创建); - 必须使用
smbpasswd -a(或pdbedit -a)把该用户添加到 Samba 用户数据库 中。
要点说明:
- Samba 密码库与系统
/etc/shadow相互独立,Samba 密码可以与系统密码不一致,修改 Samba 密码不会影响系统密码; - 默认后端
tdbsam把账号信息存放在/var/lib/samba/passdb.tdb; - 若用户不需要登录 Linux 系统,可创建为非登录用户:
useradd -s /sbin/nologin u1; - 删除系统用户后,其 Samba 账号记录不会自动清理,需要
smbpasswd -x或pdbedit -x手工删除。
3.2 smbpasswd 命令
# 添加 Samba 用户(add),会提示两次输入密码
sudo smbpasswd -a u1
# New SMB password:
# Retype new SMB password:
# Added user u1.
# 修改 Samba 用户 u1 的密码
sudo smbpasswd u1
# 删除 Samba 用户
sudo smbpasswd -x u1
# 禁用 Samba 用户(disable)
sudo smbpasswd -d u1
# 启用被禁用的用户(enable)
sudo smbpasswd -e u1
# 普通用户修改自己的 Samba 密码(不加选项、不加用户名)
smbpasswd
| 选项 | 作用 |
|---|---|
-a |
添加 Samba 用户(add) |
-x |
删除 Samba 用户 |
-d |
禁用 Samba 用户(disable) |
-e |
启用被禁用的用户(enable) |
-n |
将密码设为空 |
-s |
从标准输入读取密码,便于脚本批量添加 |
脚本批量添加示例:
(echo "123456"; echo "123456") | smbpasswd -s -a u1
3.3 pdbedit 命令
pdbedit 是 Samba 3.x 起推荐的账号管理工具,功能比 smbpasswd 更全面。
# 列出所有 Samba 用户(List)
sudo pdbedit -L
# 列出所有用户的详细信息(verbose)
sudo pdbedit -Lv
# 列出用户 u1 的详细信息
sudo pdbedit -Lv u1
# 添加用户(会提示输入密码)
sudo pdbedit -a u1
# 删除用户
sudo pdbedit -x u1
# 禁用/启用账号(通过修改账号标志位)
sudo pdbedit -c "[D]" -u u1 # 置 D 标志,禁用
sudo pdbedit -c "[]" -u u1 # 清除标志,启用
# 备份与导入账号库
sudo pdbedit -L -w > /root/samba_users.txt
| 选项 | 作用 |
|---|---|
-L |
列出所有 Samba 用户 |
-v |
与 -L 配合,显示详细信息 |
-a |
添加用户 |
-x |
删除用户 |
-c |
修改账号标志位,如 [D] 禁用、[U] 普通用户、[X] 密码永不过期 |
-u |
指定用户名 |
-w |
以 smbpasswd 文件格式输出,便于备份迁移 |
pdbedit -Lv u1 输出中的关键字段:Unix username、NT username、Account Flags([U ] 表示启用的普通用户,[DU ] 表示被禁用)、User SID、Primary Group SID、Password last set 等。
3.4 服务启动与开机自启
CentOS/RHEL 6(SysV init):
# 启动、停止、重启、重载
/etc/init.d/smb start
/etc/init.d/smb stop
/etc/init.d/smb restart
/etc/init.d/smb reload
/etc/init.d/nmb restart
# 等价的 service 写法
service smb start
service smb restart
service nmb start
service smb status
# 开机自启
chkconfig smb on
chkconfig nmb on
chkconfig --list smb
CentOS/RHEL 7(systemd):
# 启动 Samba 服务
sudo systemctl start smb nmb
# 停止 Samba 服务
sudo systemctl stop smb nmb
# 重启 Samba 服务
sudo systemctl restart smb nmb
# 重新加载配置(不断开现有连接)
sudo systemctl reload smb
# 设置开机自启
sudo systemctl enable smb nmb
# 查看服务状态
sudo systemctl status smb nmb
修改配置后使用
reload即可让新配置对新连接生效,无需restart中断已有会话;但改动[global]中的监听相关参数(如interfaces、smb ports)时需要restart。
3.5 防火墙与 SELinux 的正确处理
防火墙放行:
# CentOS 7(firewalld)
sudo firewall-cmd --permanent --add-service=samba
sudo firewall-cmd --reload
sudo firewall-cmd --list-all # 确认放行结果
# 若只需部分端口,也可逐个放行
sudo firewall-cmd --permanent --add-port=139/tcp
sudo firewall-cmd --permanent --add-port=445/tcp
sudo firewall-cmd --permanent --add-port=137/udp
sudo firewall-cmd --permanent --add-port=138/udp
sudo firewall-cmd --reload
# CentOS 6(iptables)
iptables -I INPUT -p tcp -m multiport --dports 139,445 -j ACCEPT
iptables -I INPUT -p udp -m multiport --dports 137,138 -j ACCEPT
service iptables save
service iptables restart
SELinux 设置:
# 为共享目录打上 samba 上下文(临时,重新打标签会丢失)
sudo chcon -t samba_share_t /soft
# 写入永久规则并生效(推荐)
sudo semanage fcontext -a -t samba_share_t "/soft(/.*)?"
sudo restorecon -Rv /soft
# 查看上下文
ls -Zd /soft
# 常用布尔值
sudo setsebool -P samba_enable_home_dirs on # 允许共享用户家目录
sudo setsebool -P samba_export_all_ro on # 允许以只读方式导出任意目录
sudo setsebool -P samba_export_all_rw on # 允许以读写方式导出任意目录
sudo getsebool -a | grep samba # 查看所有 samba 相关布尔值
原始笔记中常见 sudo iptables -F + sudo setenforce 0 的写法,属于不推荐的做法:
| 不推荐写法 | 问题 | 推荐替代 |
|---|---|---|
sudo iptables -F |
CentOS 7 默认防火墙是 firewalld,iptables -F 清空的是底层链表,规则会被 firewalld 重新下发,无法可靠放行;且直接清空所有规则等于关闭主机防护 |
sudo firewall-cmd --add-service=samba --permanent && sudo firewall-cmd --reload;实验环境可临时 sudo systemctl stop firewalld |
sudo setenforce 0 |
全局关闭 SELinux 强制模式,掩盖真实的上下文配置问题,重启后失效,生产环境不可接受 | 按需精确放开:sudo setsebool -P samba_enable_home_dirs on、sudo chcon -t samba_share_t /soft |
setenforce 0只能作为实验室排错时的临时手段(用于快速判断故障是否由 SELinux 引起),确认后应恢复setenforce 1并改用setsebool/chcon精确授权。
3.6 实战案例一:匿名可读共享
需求:发布一个所有人无需密码即可浏览和下载的共享 software,对应目录 /soft。
第 1 步:编辑配置文件
CentOS 6(Samba 3.x)可使用 security = share:
[global]
workgroup = MYGROUP
server string = li.cluster.com %v
security = share # 改为 share,匿名模式
passdb backend = tdbsam
load printers = yes
cups options = raw
[homes]
comment = Home Directories
browseable = no
writable = yes
[test]
comment = public for everyone
path = /test
guest ok = yes # 允许匿名登录
browseable = yes
CentOS 7(Samba 4.x,share 模式已废弃)应改用:
[global]
workgroup = MYGROUP
server string = Samba Server Version %v
log file = /var/log/samba/log.%m
max log size = 50
security = user
map to guest = Bad User # 关键:用户名不存在时降级为 guest
guest account = nobody
passdb backend = tdbsam
load printers = yes
cups options = raw
[software]
comment = good software
path = /soft
guest ok = yes
browseable = yes
writeable = no
第 2 步:创建目录并设置属主权限
sudo mkdir /soft
sudo chown uplooking:uplooking /soft
# 匿名用户以 nobody 身份访问,只读共享保证 o+rx 即可
sudo chmod 755 /soft
echo "hello smb" > /soft/1_hello.txt
CentOS 6 示例目录:
mkdir /test
ls -ld /test
# drwxr-xr-x 5 root root 4096 /test/
第 3 步:SELinux 上下文
sudo chcon -t samba_share_t /soft
# 永久规则
sudo semanage fcontext -a -t samba_share_t "/soft(/.*)?"
sudo restorecon -Rv /soft
第 4 步:防火墙放行
# CentOS 7
sudo firewall-cmd --add-service=samba --permanent
sudo firewall-cmd --reload
# CentOS 6
iptables -I INPUT -p tcp -m multiport --dports 139,445 -j ACCEPT
service iptables save
第 5 步:启动服务
# CentOS 7(仅用 IP 访问时无需 nmb)
sudo systemctl restart smb
sudo systemctl enable smb
# CentOS 6
/etc/init.d/smb reload
chkconfig smb on
第 6 步:客户端验证
smbclient -L //192.168.0.183 # 匿名查看,可见 software 共享
smbclient //192.168.0.183/software # 匿名登录
# CentOS 6 示例
smbclient -L //10.0.0.2
smbclient //10.0.0.2/test
此时匿名用户只能下载,不能上传/删除。
扩展:让匿名用户可写
在共享段加上 writable = yes。但仅服务允许还不够 —— 匿名用户在 Samba 中以 nobody 身份操作,还必须保证系统目录对 nobody(即 other 位)可写:
ls -ld /test
# drwxr-xr-x 5 root root 4096 /test/
chmod 757 /test # 让 other 具备 rwx
再次测试即可上传、改名、删除:
smbclient //10.0.0.2/test
smb: \> put install.log
smb: \> rename install.log install
smb: \> rm install.log
扩展:匿名隐藏共享(练习)
创建一个匿名可登录但不在浏览列表中显示的共享资源:
[test]
comment = public for everyone
path = /test
guest ok = yes
browseable = no
知道共享名的用户可直接 \\IP\test 访问,但在浏览列表中看不到。
share 模式要点总结(CentOS 6):
- share 模式下,
smbpasswd -a添加的普通用户都无法使用(家目录和共享目录都登录不了); browseable控制匿名用户客户端是否可见资源;public/guest ok控制匿名用户是否可以登录资源;writable控制服务层面是否允许写;- 匿名用户以
nobody身份上传,普通用户以自己的身份上传; - 因此除了服务
writable = yes之外,还需共享目录在系统级别有对应的写权限。
share 与 user 模式四种组合对比(RHEL 6):
| 模式 | 共享允许匿名 | Linux 客户端 | Windows 客户端 |
|---|---|---|---|
| share | 是 | 匿名可登录 | 匿名可登录 |
| share | 否 | 意义不大 | 意义不大 |
| user | 是 | 匿名和普通都可登录 test,普通也可登录家目录 | 普通可登录家目录和 test,匿名不能登录 test |
| user | 否 | 匿名不可登录任何资源;普通可登录 test 和家目录 | 同 Linux |
正常使用场景为第一种(share + 允许匿名)和第四种(user + 拒绝匿名)。
总结:share 模式只允许匿名登录;user 模式只允许普通用户登录。Samba 最常用的是 user 模式(因为要做精细权限控制)。
3.7 实战案例二:指定用户可读写的私有共享
需求:共享 /opt/upload,只有用户 u1 和 u2 可以访问,其中 u1 可读写,u2 只读,拒绝匿名用户。
第 1 步:创建系统用户并加入 Samba 账号库
# 1. 创建系统用户(不允许登录 shell)
sudo useradd -s /sbin/nologin u1
sudo useradd -s /sbin/nologin u2
# 2. 将其加入 Samba 用户库并设置 Samba 密码
sudo smbpasswd -a u1
sudo smbpasswd -a u2
# 3. 确认
sudo pdbedit -L
第 2 步:创建目录与设置属主权限
sudo mkdir -p /opt/upload
sudo chown u1:u1 /opt/upload
sudo chmod 755 /opt/upload
共享目录的属主/属组决定了 Samba 用户实际能否读写,需与
smb.conf中的valid users、write list配合规划。Samba 权限受「服务配置」与「Linux 文件系统权限」双重约束,两者取交集。
第 3 步:配置共享
[upload]
comment = Upload
path = /opt/upload
guest ok = no # 拒绝匿名
browseable = yes
writeable = yes
valid users = u1,u2,+g1 # 允许访问的用户和组
write list = u1 # 读写列表
read list = u2,+g1 # 只读列表
create mode = 0344 # 控制新建文件的权限
force create mode = 0344
directory mode = 0777 # 控制新建目录的权限
force directory mode = 0777
hosts deny = all # 禁止所有客户端
hosts allow = 192.168.0.0/24 except 192.168.0.222 # 仅放行本网段,排除 .222
第 4 步:SELinux 与防火墙
sudo semanage fcontext -a -t samba_share_t "/opt/upload(/.*)?"
sudo restorecon -Rv /opt/upload
sudo firewall-cmd --add-service=samba --permanent
sudo firewall-cmd --reload
第 5 步:检查语法并重启
sudo testparm
# CentOS 7
sudo systemctl restart smb nmb
# CentOS 6
/etc/init.d/smb restart
第 6 步:客户端验证
smbclient -L //192.168.0.183 -U u1
smbclient //192.168.0.183/upload -U u1 # 可上传
smbclient //192.168.0.183/upload -U u2 # 只能下载
3.8 实战案例三:多用户组协作共享(SGID + force group)
需求:smb 组的所有成员共同使用 /data/team 目录,组内成员都可读写彼此的文件,但只能删除自己创建的文件;组外用户与匿名用户一律拒绝。
第 1 步:准备组和用户
groupadd smb # 创建组
useradd -s /sbin/nologin -G smb u1
useradd -s /sbin/nologin -G smb u2
# 或把已有用户加入组
gpasswd -a u1 smb # 把用户加入组中
id u1
smbpasswd -a u1
smbpasswd -a u2
第 2 步:创建目录,设置属组、SGID 与粘滞位
sudo mkdir -p /data/team
sudo chgrp smb /data/team
# 2770:组内可读写执行;SGID(2) 使目录内新建文件自动继承属组 smb;other 无任何权限
sudo chmod 2770 /data/team
# 粘滞位:只有文件属主(和 root)能删除自己的文件
sudo chmod o+t /data/team
ls -ld /data/team
# drwxrws--T 2 root smb 4096 /data/team
- SGID(
chmod g+s或权限位 2xxx):作用于目录时,该目录下新建的文件/子目录自动继承目录的属组,是组协作的基础; - 粘滞位(
chmod o+t或权限位 1xxx):目录内的文件只有其属主可以删除或改名,即使其他人对目录有w权限,与/tmp目录同理。
粘滞位是 Linux 文件系统层面的限制,与 Samba 配置无关,因此必须在服务器本地目录上单独设置。
第 3 步:配置共享,使用 force group 兜底
[team]
comment = Team collaboration directory
path = /data/team
guest ok = no
browseable = yes
writable = yes
valid users = @smb
write list = @smb
force group = smb # 强制新建文件的属组为 smb(与 SGID 双重保障)
create mask = 0660
directory mask = 0770
inherit permissions = no
如果希望所有成员上传的文件统一归属某个账号(放弃「只能删自己」的能力,换取完全一致的权限),可改用 force user:
force user = teamadmin
force group = smb
第 4 步:SELinux、防火墙、启动服务
sudo semanage fcontext -a -t samba_share_t "/data/team(/.*)?"
sudo restorecon -Rv /data/team
sudo setsebool -P samba_export_all_rw on # 若目录不在标准位置且需读写
sudo firewall-cmd --add-service=samba --permanent
sudo firewall-cmd --reload
sudo testparm
sudo systemctl restart smb nmb # CentOS 7
# service smb restart; service nmb restart # CentOS 6
第 5 步:验证
smbclient //192.168.0.183/team -U u1
smb: \> put a.txt
smb: \> ls
# 切换为 u2 登录,应能读写 a.txt,但删除 a.txt 会失败
smbclient //192.168.0.183/team -U u2
smb: \> rm a.txt
# NT_STATUS_CANNOT_DELETE
四、user 模式下的精细权限控制
本章内容基于 RHEL/CentOS 6 + Samba 3.x 实测总结,配置思路同样适用于 CentOS 7。
4.1 普通用户下载与上传的条件
- 下载条件:登录用户对目标文件有
r权限; - 上传条件:登录用户对共享目录有
w权限,且服务配置writable = yes(或read only = no),并且该用户在write list中(若使用了该参数)。
4.2 实现用户之间互相不能删除文件
现象:默认情况下,只要文件拥有者对文件有写权限,其他人(包括自己)就可以删除它。
# a 上传的文件
-rwxr--r-- 1 a a 0 123
-rwxr--r-- 1 a a 0 456
# b 上传的文件
-rwxr--r-- 1 b b 0 678
若将文件权限改为 577(拥有者无写权限),别人删除失败:
chmod 577 /test/456
# -r-xrwxrwx 1 a a 0 456
# b 删除 -> NT_STATUS_CANNOT_DELETE
若将文件权限改为 200(拥有者只有写权限),别人删除成功:
chmod 200 /test/456
# --w------- 1 a a 0 456
# b 删除 -> 成功
结论:只要文件拥有者对该文件有写权限,别人(包括自己)就可以删除;拥有者无写权限,则自己和别人都不能删除。
实现「只能删自己的、不能删别人的」:
chmod o+t /test # 设置粘滞位
同时要求文件 owner 对自己的文件有写权限。
4.3 create mask 与 directory mask 实践
直接定义上传文件/目录的权限:
[test]
comment = public for everyone
path = /test
browseable = yes
read only = yes
writable = yes
create mask = 0444 # 上传文件权限为 444(默认 744)
directory mask = 0666 # 上传目录权限为 666(默认 755)
/etc/init.d/smb restart
4.4 精细控制用户读写权限
[test]
comment = public for everyone
path = /test
guest ok = no # 拒绝匿名
valid users = a,b # 只允许 a、b 访问
write list = a # 只有 a 可写(上传)
chmod 757 /test
/etc/init.d/smb reload
参数使用要点:
valid users = a,b,@group:允许用户 a、b 及 group 组的成员;write list = a,@group:允许写入的用户列表;read list与write list相反,注意它不是控制「哪些人只能读」的额外白名单,而是与write list反义的写列表;- 组前缀可以使用
@或+; - 注意参数是
users(复数),不要误写为user。
练习 1:a 用户只能上传(不能下载自己上传的文件),b 用户只能下载,拒绝匿名和其它用户。
答案:在上面配置基础上加
create mask = 0344(属主无 r 权限,因此 a 上传后自己读不了;other 有 r,b 可下载)。
练习 2:a 可上传下载,b 只能下载但不能下载 a 上传的文件,拒绝匿名和其它用户。
答案:在上面配置基础上加
create mask = 0704(属主 a 可读写,other 无读权限,b 读不到 a 的文件)。
4.5 包含组的精细控制
需求:a 可上传下载,b 只能下载,smb 组成员可登录并上传下载,拒绝其他普通用户和匿名用户。
[test]
comment = public for a,b,@smb
path = /test
public = no
valid users = a,b,@smb # 注意 users 不要写成 user
write list = a,@smb # @ 也可以使用 +
创建用户和组:
groupadd smb
useradd smb1 -g smb
useradd smb2 -g smb
smbpasswd -a smb1
smbpasswd -a smb2
id smb1
# uid=521(smb1) gid=521(smb) groups=521(smb)
4.6 综合案例:boss / secretary / it 组
需求:
boss:可上传下载(可下载所有人的文件)、删除自己上传的文件;secretary:只能下载(可下载所有人的文件);it组成员(it1、it2):可登录、上传、下载和删除自己的文件;组成员之间不能互删、不能互相下载别人的文件,但可以下载 boss 上传的文件;- 拒绝其他普通用户和匿名用户。
useradd boss
useradd secretary
groupadd it
useradd -g it it1
useradd -g it it2
smbpasswd -a boss
smbpasswd -a secretary
smbpasswd -a it1
smbpasswd -a it2
[test]
comment = hahahahahaha
path = /test
public = no
browseable = no
valid users = boss,secretary,@it
write list = boss,@it
create mask = 0704
mkdir /test
chmod 757 /test
chmod o+t /test
扩展讨论:
- 若再加一个
sale组,需求与it相同:由于权限只能用 owner/group/other 三档区分,sale和it组成员会互相能下载。最好的做法是每个组使用不同的目录(分别建共享)。若硬要放在同一目录,可把两个组的 GID 改成同一个公共组,但这相当于把两组合并对待,失去隔离意义。 - 若需求变为「boss 能删除所有人的文件」:理论上无法仅靠 Samba 配置实现(粘滞位会阻止);一种方法是
chown boss.boss /test让 boss 成为目录 owner(目录属主可删除粘滞位目录内的任意文件);另一种方法是在共享段使用admin users = boss,让 boss 以 root 身份操作。
4.7 综合案例:a / b / c 差异化权限
需求:
- a:上传下载(可下载所有人的文件);
- b:只能下载(可下载所有人的文件);
- c:可上传,但只能下载自己上传的文件;
- 都可删除自己的文件,互相不能删;拒绝其他用户和匿名用户。
关键是让 a、c 上传的文件权限分别为 rwx---r-- 形式,并把 c 加入 a 组:
useradd a
useradd b
useradd c
usermod -G a c
smbpasswd -a a
smbpasswd -a b
smbpasswd -a c
mkdir /test
chmod 757 /test
chmod o+t /test
[test]
comment = test resource
path = /test
guest ok = no
browseable = yes
valid users = a,b,c
write list = a,c
create mask = 0704
/etc/init.d/smb restart
另一种思路(可选):让 a 上传文件为 rwxr-----、c 上传文件为 rwxr-----,并把 b 加入 a、c 组,通过组权限位让 b 能读到二者的文件。
4.8 不同用户不同 create mask(用户子配置文件 config file = %U)
当不同用户对同一共享需要不同权限策略(例如 u1 可上传下载、u2 只能下载且看不到 u1 上传的文件)时,可在 [global] 中使用 config file 为每个用户指定独立的配置文件:
# [global] 中添加
config file = /etc/samba/smb.conf.%U # %U 表示登录用户名
%U 是 Samba 的变量替换符,表示 当前登录的用户名。用户 u1 登录时,Samba 会尝试加载 /etc/samba/smb.conf.u1;若该文件存在则以它替代主配置生效,不存在则继续使用 /etc/samba/smb.conf。由此可为单个用户定制共享策略。
需求示例:a 上传为默认 0744,c 上传为 0344(属主无读权限)。
主配置 /etc/samba/smb.conf:
[test]
comment = 35's test resource
path = /test
public = no
browseable = yes
valid users = a,b,c
write list = a
create mask = 0744
为 c 用户单独创建子配置文件:
vim /etc/samba/smb.conf.c
[test]
comment = 35's test resource
path = /test
writable = yes
create mask = 0344 # 没有读权限
/etc/init.d/smb restart
config file的另一种替代思路是把同一物理目录做成两个不同共享名,在不同共享段里分别控制权限。
五、客户端访问
5.1 Linux 客户端:smbclient
smbclient 由 samba-client 包提供,无需挂载即可直接测试和访问共享,是排查共享是否生效的首选工具。
列举服务器上的共享:
smbclient -L //192.168.0.183
smbclient -L //10.0.0.2
# Password: # 直接回车即以匿名身份查看
-L 表示列出目标主机对外提供的共享名、类型与注释。默认会提示输入密码,直接回车即以匿名身份查看;也可用 -U 指定用户:
smbclient -L //10.0.0.2 -U a
smbclient -L //192.168.0.183 -U u1
# 新版本可用 -N 表示不提示密码(匿名)
smbclient -L //192.168.0.183 -N
注意 browseable = No 的共享不会出现在列表中,但仍可直接连接。若登录失败报 NT_STATUS_LOGON_FAILURE,检查该系统用户是否已通过 smbpasswd -a 加入 Samba 账号库。
交互式登录共享:
smbclient //192.168.0.183/software
smbclient //192.168.0.183/share -U u1
smbclient //10.0.0.2/a -U a
连接成功后进入 smb: \> 提示符,可使用类似 FTP 的交互命令:
| 命令 | 作用 |
|---|---|
ls |
列出共享内的文件 |
pwd |
显示当前所在目录 |
cd |
切换目录 |
mkdir |
创建目录 |
get 1_hello.txt |
下载文件 |
mget |
批量下载 |
put file.txt |
上传文件(需共享可写) |
mput |
批量上传 |
rm |
删除文件 |
rename |
重命名文件 |
lcd |
切换本地目录 |
!命令 |
执行本地 shell 命令 |
help / ? |
查看命令帮助 |
exit 或 quit |
退出 |
操作示例:
smbclient //10.0.0.2/a -U a
# smb: \> pwd
# Current directory is \\10.0.0.2\a\
# smb: \> ls
# smb: \> put install.log
# smb: \> get vvv
# smb: \> rm vvv
# smb: \> rename install.log install
其他常用选项:
smbclient //server/share -U user%password # 在命令行直接给出密码(会暴露在历史记录中)
smbclient //server/share -A /root/.smbcred # 从凭据文件读取账号密码
smbclient //server/share -c "ls; get a.txt" # 非交互执行命令,便于脚本化
smbclient //server/share -m SMB3 # 指定协议版本
5.2 Linux 客户端:mount 挂载 cifs
挂载依赖 cifs-utils 包提供的 mount.cifs,需先安装:
sudo yum install cifs-utils -y
基本挂载:
# 用匿名用户挂载
sudo mount //192.168.0.183/software /mnt -o guest
# 指定用户名挂载(会提示输入密码)
sudo mount //192.168.0.183/software /mnt -o username=u1
# 显式指定文件系统类型
mount -t cifs -o username=a //10.0.0.2/a /mnt
# Password:
# 同时给出用户名和密码(不安全,密码会进入命令历史与 ps 输出)
sudo mount -t cifs //192.168.0.183/share /mnt -o username=u1,password=123456
挂载后即可使用 cp、ls、mv、rm 等普通命令操作,df -h 可看到挂载点。卸载使用 umount /mnt。
常用挂载选项:
| 选项 | 说明 |
|---|---|
username= |
登录 Samba 的用户名 |
password= |
密码(不推荐明文写在命令或 fstab 中) |
guest |
匿名挂载,等价于空用户名空密码 |
credentials= |
指定凭据文件路径,避免密码明文 |
uid= / gid= |
挂载后本地看到的文件属主/属组,常设为使用该目录的本地用户,否则默认全部归 root |
file_mode= / dir_mode= |
挂载后本地呈现的文件/目录权限,如 file_mode=0644,dir_mode=0755 |
vers= |
SMB 协议版本,如 vers=1.0、vers=2.0、vers=2.1、vers=3.0。服务端禁用 SMB1 时必须指定 2.0 及以上 |
iocharset=utf8 |
指定字符集,解决中文文件名乱码 |
sec= |
认证方式,如 ntlmssp(默认)、ntlm、krb5 |
ro / rw |
只读 / 读写挂载 |
_netdev |
声明该挂载依赖网络,供 systemd 在网络就绪后再挂载 |
noauto |
开机不自动挂载,需手工 mount |
完整示例:
sudo mount -t cifs //192.168.0.183/share /mnt/samba \
-o credentials=/root/.smbcred,uid=1000,gid=1000,file_mode=0644,dir_mode=0755,vers=3.0,iocharset=utf8
credentials 凭据文件(避免明文密码):
sudo vim /root/.smbcred
username=u1
password=your_pass
domain=MYGROUP
# 必须收紧权限,否则密码等于公开
sudo chmod 600 /root/.smbcred
sudo chown root:root /root/.smbcred
开机自动挂载(/etc/fstab):
//192.168.0.183/software /mnt/samba cifs username=u1,password=your_pass,_netdev 0 0
推荐使用凭据文件的写法:
//192.168.0.183/share /mnt/samba cifs credentials=/root/.smbcred,uid=1000,gid=1000,vers=3.0,iocharset=utf8,_netdev 0 0
写入后可先测试:
sudo mount -a
df -h | grep samba
生产环境建议将凭据写入独立文件(如
/root/.smbcred),并通过credentials=/root/.smbcred引用,避免密码明文暴露在/etc/fstab中(/etc/fstab默认对所有用户可读)。若网络未就绪导致开机挂载失败,务必加_netdev,或改用noauto+ 手工/自动挂载单元。
5.3 Windows 客户端访问
方式一:直接访问 UNC 路径
- 打开「运行」(Win + R),输入
\\192.168.1.x(Samba 服务器 IP)或\\192.168.1.x\共享名; - 在弹出的认证窗口中输入 Samba 用户名和密码;
- 匿名共享则无需输入凭据即可进入。
方式二:映射网络驱动器(开机自动连接)
- 右键「我的电脑 / 此电脑」→ 工具 → 映射网络驱动器;
- 「文件夹」处填写
\\10.0.0.2\a; - 勾选「登录时重新连接」,在「其他用户名 / 使用其他凭据」中填写用户名和密码。
命令行方式:
net use Z: \\192.168.0.183\share /user:u1 your_pass /persistent:yes
net use :: 查看当前连接
net use Z: /del :: 断开指定驱动器
net use * /del :: 清除所有连接缓存(排错常用)
Windows 凭据管理器:控制面板 → 用户账户 → 凭据管理器 → Windows 凭据,可查看/添加/删除已保存的 Samba 服务器凭据。当密码修改后连接仍失败,通常是旧凭据被缓存,需在此删除对应条目,或执行 net use * /del 后重试。
Windows 端常见无法访问的原因:
- Windows 防火墙拦截,或第三方安全软件阻止了「文件和打印机共享」;测试环境可先关闭 Windows 防火墙;
- 客户端缓存了旧的错误凭据(用
net use * /del或凭据管理器清除); - Windows 10/11 默认关闭了 SMB1 和「不安全的来宾登录」,访问匿名共享会报「你不能访问此共享文件夹,因为你的组织的安全策略阻止未经身份验证的来宾访问」。解决办法:让服务端启用 SMB2/SMB3 并使用带账号的访问;或在客户端组策略「计算机配置 → 管理模板 → 网络 → Lanman 工作站 → 启用不安全的来宾登录」中开启(不推荐);
- 工作组名称不一致导致网上邻居中看不到(但用 IP 直连仍可用);
- 服务器端未启动
nmb,导致无法通过计算机名访问,改用 IP 即可; - 445 端口被运营商或本地策略封禁。
六、状态查看与运维
6.1 smbstatus 查看连接与锁
sudo smbstatus # 查看所有活动会话、已连接共享和文件锁
sudo smbstatus -b # 仅显示简要的会话列表(brief)
sudo smbstatus -S # 仅显示共享连接情况(shares)
sudo smbstatus -L # 仅显示文件锁(locks)
sudo smbstatus -p # 仅显示 smbd 进程列表
sudo smbstatus -u u1 # 只看指定用户的连接
输出包含三部分:
- Samba version / PID / Username / Group / Machine:哪个用户从哪台机器连接;
- Service (pid) machine Connected at:连接了哪些共享,连接时间;
- Locked files:当前被打开/锁定的文件,可定位「文件被占用无法删除」的来源。
强制断开某个连接可直接结束对应的 smbd 进程(谨慎操作):
sudo kill <PID>
6.2 日志位置与级别调整
日志目录为 /var/log/samba/:
| 文件 | 内容 |
|---|---|
log.smbd |
smbd 主进程日志 |
log.nmbd |
nmbd 主进程日志 |
log.<客户端名或IP> |
由 log file = /var/log/samba/log.%m 生成的每客户端日志,排错主要看这里 |
调整日志级别(0~10,默认 0 或 1,数字越大越详细):
[global]
log file = /var/log/samba/log.%m
max log size = 50 # KB,0 表示不限制
log level = 3 # 排错时临时提高,排完改回 1
# 也可分模块设置
# log level = 1 auth:3 winbind:2
sudo systemctl reload smb
tail -f /var/log/samba/log.192.168.0.100
其他排错工具:
testparm -s # 校验配置
smbclient -L //localhost -N # 本机自测共享是否发布
ss -tulnp | grep -E 'smbd|nmbd' # 检查监听端口(CentOS 7)
netstat -ntlup | grep bd # CentOS 6
ausearch -m avc -ts recent # 查看近期 SELinux 拒绝记录
grep smbd /var/log/audit/audit.log | audit2why
6.3 打印共享简述
Samba 可以把 Linux(CUPS)上的打印机共享给 Windows 客户端。
[global]
load printers = yes # 自动加载 /etc/printcap 中的全部打印机
printing = cups # 打印系统类型:cups / lprng / bsd
printcap name = cups
cups options = raw # raw 表示打印数据由客户端驱动生成,服务端不再处理
[printers]
comment = All Printers
path = /var/spool/samba # 打印假脱机目录
browseable = no
guest ok = no
writable = no
printable = yes # 打印共享必须为 yes
# 单独共享某台打印机
[hp-laser]
comment = HP LaserJet
path = /var/spool/samba
printer name = hp-laser
printable = yes
guest ok = yes
valid users = @printusers
要点:
printable = yes是打印共享的标志,普通文件共享绝不能设置;- 假脱机目录
/var/spool/samba需要1777权限(含粘滞位); cups options = raw时,Windows 端需安装与打印机匹配的驱动;- 可另外配置
[print$]共享用于向 Windows 客户端自动分发打印驱动。
6.4 Samba 加入 AD/NT 域简述
在有 Windows 域控的环境中,可让 Samba 使用域账号认证,避免在 Linux 端重复建账号。核心是 security = ads(AD 域)或 security = domain(NT 域),并启用 winbindd。
[global]
workgroup = EXAMPLE # 域的 NetBIOS 名
realm = EXAMPLE.COM # AD 域的 Kerberos realm(大写)
security = ads
idmap config * : backend = tdb
idmap config * : range = 10000-19999
idmap config EXAMPLE : backend = rid
idmap config EXAMPLE : range = 100000-999999
winbind use default domain = yes
winbind offline logon = yes
template shell = /bin/bash
template homedir = /home/%D/%U
大致步骤:
# 1. 安装依赖
yum install samba samba-winbind samba-winbind-clients krb5-workstation -y
# 2. 确保 DNS 指向域控、时间与域控同步(Kerberos 对时间敏感)
ntpdate <域控IP> # 或使用 chronyd
# 3. 加入域
net ads join -U Administrator
# NT 域则使用:net rpc join -U Administrator
# 4. 启动 winbind
systemctl enable --now winbind # CentOS 7
service winbind start # CentOS 6
# 5. 验证
net ads testjoin
wbinfo -u # 列出域用户
wbinfo -g # 列出域组
wbinfo -a EXAMPLE\\user # 测试域用户认证
getent passwd EXAMPLE\\user # 需在 /etc/nsswitch.conf 中加入 winbind
在 /etc/nsswitch.conf 中加入 winbind,使系统能解析域账号:
passwd: files winbind
group: files winbind
此后共享段中可直接使用域账号与域组:
[share]
path = /data/share
valid users = @"EXAMPLE\Domain Users"
write list = @"EXAMPLE\IT"
若无域环境,保持
security = user+ 本地账号即可,本节可跳过。
6.5 注意事项汇总
- 权限一致性:Samba 权限受自身配置和 Linux 文件系统权限双重约束,需确保共享目录对系统用户有足够的读写权限。
- SELinux:若开启 SELinux,共享目录需设置正确的上下文(
samba_share_t),必要时执行setsebool -P samba_enable_home_dirs on。 - 防火墙:确保已开放 SMB 相关端口(TCP 139、445,UDP 137、138)。
security模式:share模式已在新版 Samba(4.x / CentOS 7)中废弃,推荐使用user模式 +map to guest = Bad User。- 用户隔离:Samba 用户密码与系统用户密码独立管理,修改 Samba 密码不会影响系统密码。
- 配置备份:修改
smb.conf前建议先备份,并使用testparm验证语法。 - 协议版本:禁用 SMB1(
min protocol = SMB2)可显著提升安全性,但需评估老旧客户端与设备的兼容性。
七、排错清单
按「网络 → 防火墙 → SELinux → 服务配置 → 系统权限」的顺序逐层排查。
7.1 无法浏览到共享列表
| 可能原因 | 检查与解决 |
|---|---|
| 服务未启动 | systemctl status smb nmb / service smb status;用 ss -tulnp 过滤 smbd 确认监听 |
| 配置语法错误导致未加载 | testparm -s,确认输出 Loaded services file OK. |
| 防火墙拦截 | firewall-cmd --list-all 确认放行 samba;CentOS 6 检查 iptables -L -n |
browseable = no |
该共享被故意隐藏,直接用 smbclient //IP/共享名 或 \\IP\共享名 连接 |
hosts allow / hosts deny 拦截 |
检查全局段与共享段的访问控制列表,注意 hosts deny = all 的存在 |
available = no |
共享被禁用,改为 yes 或删除该行 |
| 用不了主机名 | 未启动 nmb 或 NetBIOS 名称解析失败,改用 IP 访问,或配置 WINS / lmhosts |
| 客户端和服务器不在同一广播域 | 网上邻居自动发现依赖广播,跨网段需 WINS 或直接用 IP |
7.2 能看到共享但打不开(认证失败)
| 现象 / 原因 | 解决 |
|---|---|
NT_STATUS_LOGON_FAILURE |
该系统用户未加入 Samba 账号库,执行 smbpasswd -a 用户名;或密码输错;用 pdbedit -L 确认账号存在 |
| 账号被禁用 | pdbedit -Lv 用户名 查看 Account Flags 是否为 [DU...],用 smbpasswd -e 启用 |
NT_STATUS_ACCESS_DENIED |
用户不在 valid users 中,或被 invalid users 拒绝 |
| 匿名访问被拒 | CentOS 7 需 security = user + map to guest = Bad User + 共享段 guest ok = yes |
| Windows 缓存了旧凭据 | net use * /del,或在凭据管理器中删除该服务器条目 |
NT_STATUS_BAD_NETWORK_NAME |
共享名拼写错误,或 path 指向的目录不存在 |
| 系统用户 shell 为 nologin 导致 PAM 拒绝 | Samba 认证一般不受 shell 限制;若配置了 obey pam restrictions = yes,检查 PAM 与账号是否被锁定(passwd -S 用户名) |
7.3 可读不可写
依次检查三个层面:
- 服务层:共享段是否
writable = yes(或read only = no);同义/反义参数是否被后面的行覆盖;该用户是否在write list中,是否被read list命中; - 文件系统层:
ls -ld /共享目录确认登录用户对目录有w和x权限。匿名共享要给 other 位写权限(如chmod 757 /test),私有共享把目录属主/属组改成对应用户或组; - SELinux 层:
ls -Zd /共享目录确认是samba_share_t,只读上下文或错误上下文会导致只能读不能写;必要时setsebool -P samba_export_all_rw on。
另外注意粘滞位与 create mask:create mask 过严(如 0444)会导致上传后的文件自己都改不动;粘滞位会阻止删除别人的文件(这通常是预期行为)。
7.4 中文文件名乱码
服务端配置:
[global]
unix charset = UTF-8
dos charset = cp936
display charset = UTF-8
Linux 客户端挂载时指定字符集:
mount -t cifs //IP/share /mnt -o username=u1,iocharset=utf8
同时确认服务器 shell 的 LANG 环境变量(echo $LANG 应为 zh_CN.UTF-8 或 en_US.UTF-8),以及 Windows 端系统区域设置。
7.5 SELinux 拒绝访问
# 快速判断是否 SELinux 引起(临时)
getenforce
setenforce 0 # 若此时正常,则问题在 SELinux;确认后立即 setenforce 1
# 查看被拒绝的记录并获得建议
ausearch -m avc -ts recent
grep smbd /var/log/audit/audit.log | audit2why
grep smbd /var/log/audit/audit.log | audit2allow -M mysamba # 生成自定义策略(谨慎)
# 正确做法
semanage fcontext -a -t samba_share_t "/共享目录(/.*)?"
restorecon -Rv /共享目录
setsebool -P samba_enable_home_dirs on
setsebool -P samba_export_all_rw on
7.6 SMB1 被禁导致老客户端连不上
现象:Windows XP、老式打印机/扫描仪、部分嵌入式 NAS 无法连接,日志出现协议协商失败。
- 首选方案:升级客户端或设备固件,使其支持 SMB2/SMB3;
- 隔离方案:单独部署一台仅供老设备使用的 Samba 实例,放在独立网段并严格限制
hosts allow; - 临时兼容(有安全风险,仅限内网隔离环境):
[global]
min protocol = NT1
max protocol = SMB3
# 老客户端可能还需要
ntlm auth = yes
server min protocol = NT1
反之,若是新版 Linux 客户端连接老服务器失败,则在挂载时降低版本:
mount -t cifs //IP/share /mnt -o username=u1,vers=1.0
7.7 445 端口被占用或被拦截
# 检查端口占用(若被其他程序占用,smbd 会启动失败)
ss -tulnp | grep -E ':445|:139'
netstat -ntlup | grep -E '445|139'
lsof -i :445
# 检查是否被防火墙拦截
firewall-cmd --list-all
iptables -L -n --line-numbers
# 从客户端测试连通性
telnet 192.168.0.183 445
nc -zv 192.168.0.183 445
nmap -p 139,445 192.168.0.183
其他可能:
- 运营商在公网侧封禁 139/445,因此 Samba 不适合直接跨公网使用,应通过 VPN 或 SSH 隧道;
- 云主机安全组未放行入站 139/445;
- 若确需更换端口,可在
[global]中设置smb ports = 445 139(注意多数 Windows 客户端不支持自定义端口)。
7.8 排错速查命令清单
testparm -s # 配置语法
systemctl status smb nmb # 服务状态(CentOS 7)
service smb status # 服务状态(CentOS 6)
ss -tulnp | grep -E 'smbd|nmbd' # 监听端口
smbstatus # 当前连接与文件锁
pdbedit -L # Samba 账号列表
pdbedit -Lv u1 # 账号详情与标志位
ls -ld /共享目录 # 系统权限
ls -Zd /共享目录 # SELinux 上下文
getsebool -a | grep samba # SELinux 布尔值
firewall-cmd --list-all # 防火墙放行情况
tail -f /var/log/samba/log.客户端IP # 实时日志
smbclient -L //localhost -N # 本机自测
八、练习
练习一:配置一个基本的 Samba 共享
-
处理防火墙和 SELinux(推荐精确放行,实验室可临时关闭):
# 不推荐但常见于旧笔记的做法 sudo iptables -F sudo setenforce 0 # 推荐做法 sudo firewall-cmd --add-service=samba --permanent sudo firewall-cmd --reload sudo chcon -t samba_share_t /soft -
编辑配置文件增加一个共享:
sudo vim /etc/samba/smb.conf[software] comment = good software path = /soft guest ok = yes browseable = yes writeable = no -
创建共享目录:
sudo mkdir /soft sudo chown uplooking:uplooking /soft echo "hello smb" > /soft/1_hello.txt -
启动/重启服务:
sudo systemctl restart smb # CentOS 7 # /etc/init.d/smb restart # CentOS 6 -
列出共享并登录共享:
smbclient -L //192.168.0.* smbclient //192.168.0.*/software
练习二:创建一个 Samba 用户并观察状态变化
按以下步骤操作,并观察每步中用户详细信息的差异:
- 创建一个系统用户
u1; - 修改用户
u1在 Samba 服务里的密码; - 把用户
u1添加为 Samba 服务的用户; - 列出 Samba 用户
u1的详细信息; - 把用户
u1踢出 Samba 用户库; - 列出 Samba 用户
u1的详细信息; - 把用户
u1重新添加为 Samba 服务的用户; - 列出 Samba 用户
u1的详细信息; - 禁用 Samba 用户
u1; - 列出 Samba 用户
u1的详细信息; - 启用 Samba 用户
u1; - 列出 Samba 用户
u1的详细信息; - 对比第 4、6、8、10、12 步详细信息的不同(重点看
Account Flags)。
参考命令:
useradd u1
smbpasswd -a u1
pdbedit -Lv u1
smbpasswd -x u1
pdbedit -Lv u1
smbpasswd -a u1
pdbedit -Lv u1
smbpasswd -d u1
pdbedit -Lv u1
smbpasswd -e u1
pdbedit -Lv u1
预期结果:删除后
pdbedit -Lv u1查不到该用户;禁用后Account Flags中出现D;启用后D消失。
练习三:禁止用户登录自己的家目录
把配置文件中 [homes] 共享的相关行注释掉:
#[homes]
# comment = Home Directories
# browseable = no
# writable = yes
然后使用普通用户验证其家目录共享不再出现:
smbclient -L //10.1.2.3 -U u1
练习四:配置精细化权限共享
按以下要求创建一个共享:
- 用户
u1和属于smb组的用户可以上传下载(valid users = u1,u2,+smb,write list = u1,+smb); - 用户
u2只能下载不能上传(通过read list或不列入write list); - 用户
u2能下载所有人上传的文件; - 用户
u2不能下载u1上传的文件(给u1单独配置文件,在其中修改上传文件的权限); - 用户之间不能删除别人上传的文件(目录加粘滞位
chmod o+t); - 该共享不显示在共享列表中(
browseable = no); - 只允许来自
192.168.0.0/24的客户端,但排除192.168.0.222(hosts allow); - 拒绝匿名用户和其他用户访问(
guest ok = no)。
准备组和用户:
groupadd smb # 创建组
gpasswd -a u1 smb # 把用户加入组中
mkdir -p /tmp/share
chmod 1777 /tmp/share # 或 chmod o+t /tmp/share
参考配置 —— 主配置文件 /etc/samba/smb.conf:
[global]
config file = /etc/samba/smb.conf.%U
# ... global 部分的其它设置省略
[share]
comment = Share data
path = /tmp/share
valid users = u1,u2,+smb
write list = u1,+smb
read list = u2
browseable = No
guest ok = no
hosts allow = 192.168.0.0/255.255.255.0 except 192.168.0.222
u1 用户专用配置文件 /etc/samba/smb.conf.u1:
[share]
comment = Share data
path = /tmp/share
valid users = u1
write list = u1
browseable = No
hosts allow = 192.168.0.0/255.255.255.0 except 192.168.0.222
create mode = 0400
force create mode = 0400
设置共享目录的粘滞位(sticky bit),使用户只能删除自己创建的文件:
sudo chmod o+t /tmp/share
通过将
u1上传文件权限设为0400,使u2等其他用户无法读取u1上传的文件,从而实现「u2 不能下载 u1 上传的文件」。
练习五:搭建匿名只读共享并用 smbclient 验证
完整操作顺序如下:
# 1. 放行防火墙(CentOS 7 默认使用 firewalld)
sudo firewall-cmd --add-service=samba --permanent
sudo firewall-cmd --reload
# 2. 编辑共享配置
sudo vim /etc/samba/smb.conf
# 3. 准备共享目录
sudo mkdir /soft
sudo chown uplooking:uplooking /soft
# 4. 处理 SELinux:为共享目录打上 samba 上下文
sudo chcon -t samba_share_t /soft
# 如需共享用户家目录,另需开启布尔值
sudo setsebool -P samba_enable_home_dirs on
# 5. 重启服务(仅用 IP 访问时无需 nmb)
sudo systemctl restart smb
# 6. 客户端验证共享是否发布成功
smbclient -L //192.168.0.183
练习六:CentOS 6 user 模式权限控制系列练习
- 创建一个匿名可登录但不在浏览列表中显示的隐藏共享(参见 3.6 扩展)。
- user 模式下实现 a 可上传下载、b 只能下载、拒绝匿名及其他用户(参见 4.4)。
- user 模式下实现 a 只能上传不能下载自己上传的文件、b 只能下载(参见 4.4 练习 1,答案:
create mask = 0344)。 - user 模式下实现 a 可上传下载、b 只能下载且不能下载 a 上传的文件(参见 4.4 练习 2,答案:
create mask = 0704)。 - user 模式下实现 boss / secretary / it 组的差异化权限(参见 4.6)。
- user 模式下实现 a / b / c 差异化权限,并用
config file = %U为不同用户设置不同create mask(参见 4.7、4.8)。 - 在第 5 题基础上增加
sale组(需求与it相同),讨论能否仅靠 Samba 参数实现;若要求 boss 能删除所有人的文件,讨论可行的实现方式(参见 4.6 扩展讨论)。
此处评论已关闭