☰
CentOS 7 Samba共享实战:从安装、配置到防火墙SELinux排错
2026/10/8 2:29:21 网站建设 项目流程

简介:这份资源是一份面向运维工程师与Linux初学者的Centos7 Samba服务器配置实战讲解,内容以PDF格式呈现,全包共1个文件,大小约392KB。资料从Samba服务的基本概念入手,重点演示了匿名共享访问与基于用户的身份验证两种典型配置流程,覆盖yum安装、smb.conf配置优化、创建共享目录、关闭防火墙与SELinux、创建smb用户、权限划分及重启服务等关键步骤,并配有命令示例和验证方法,便于读者照步骤复现,也能帮助理解SMB协议在局域网文件共享中的实际应用。当前已有1166人学习浏览,适合想在真实环境中快速部署Samba服务并掌握常见排错思路的读者参考学习。

1. 从一次共享失败说起:CentOS 7 的 Samba 实战到底解决什么

在 CentOS 7 上把 Samba 服务器配到能被 Windows 客户端直接认出来,不是写一段 smb.conf 就完事。我见过不少团队在这个共享面前卡住:文件路径没错、账号也建了,可 Windows 那边要么弹 NT_STATUS_ACCESS_DENIED,要么干脆找不到这台机器——问题往往不是 Samba 本身,而是 CentOS 7 的防火墙和 SELinux 没配对。这篇文章用实战配置的方式,讲清楚 Samba 服务从安装、共享、用户认证到排错的全过程,适合内网里需要把 Linux 目录共享给 Windows 的运维和开发,也适合刚接手 CentOS 7 文件服务器的人照着手敲。所有命令都基于 CentOS 7 默认环境,没有图形界面依赖。

2. 安装与最小可用的 Samba:CentOS 7 的包选择和第一条 smb.conf

2.1 为什么选 Samba:三个替代方案与选型理由

先回答一个最基本的问题:CentOS 7 上做文件共享,为什么不直接用 NFS 或 FTP?NFS 在 Linux 到 Linux 的场景下表现很好,透明挂载、权限跟随登录用户,但 Windows 客户端的 NFS 支持要装额外组件,而且 v4 的 Kerberos 配置在域环境里又是一层复杂度。FTP 能传文件,但不能提供共享目录锁和类似本地盘的操作体验,网页上传、断点续传都需要额外开发,权限模型也跟 POSIX 不匹配。HTTP 只能读为主,不能写。Samba 使用 SMB 协议,是 Windows 原生的协议,Windows、Mac、Linux 都能识别,还支持文件锁、打印机共享、AD 域认证,所以当你的共享对象里有 Windows 客户端,Samba 几乎是少不掉的。

这个选择也有代价:Samba 封装了一层权限转换,大文件传输场景可能有额外开销,配置不好时还会遇到 SELinux 和防火墙的双重拦截。因此我的经验是:纯 Linux 内部用 NFS,给 Windows 用 Samba,两边都需要的场景才单独起一台 Samba 服务器。如果你是开发团队,要共享一份代码目录给不同系统的 CI 机,用 Samba 的 guest 只读共享就够,别上域认证。

2.2 安装 Samba 及相关工具:yum 安装和验证

CentOS 7 官方源里自带 Samba 4.x 系列包,不要手动编译,除非你有特殊补丁需求。用 yum 装最省事:

# 安装服务端、客户端和公共工具 yum install -y samba samba-client samba-common # 确认安装后的版本 rpm -q samba samba-client samba-common

三个包分开说:samba 是服务端主程序,提供 smbd 和 nmbd;samba-client 提供 smbclient、smbstatus 等命令,后期排错离不开它;samba-common 提供 testparm、/etc/samba/smb.conf 模板等公共配置。实际安装时 samba 包会把 samba-common 作为依赖拉进来,但显式写出来可以避免某些最小化系统缺工具。如果你在内网环境装不上,先检查 yum 源是否可用,同步 CentOS 7 的 Base 和 Updates 源,再执行 update。网络不通时不要急着换源,先看 DNS 能不能解析域名——CentOS 7 新装系统经常是网卡没拿到 DNS,导致 yum 直接报 cannot resolve host。

2.3 写一个最小可用的 smb.conf:匿名共享配置

找一台测试机,先把原始配置备份,再清空重写:

cp -a /etc/samba/smb.conf /etc/samba/smb.conf.bak mkdir -p /srv/share chmod 777 /srv/share

然后用 vim 编辑 /etc/samba/smb.conf,写入下面这段:

[global] workgroup = WORKGROUP server string = CentOS 7 Samba Server security = user map to guest = Bad User guest account = nobody [public] path = /srv/share browseable = yes writable = yes guest ok = yes create mask = 0664 directory mask = 0775

说明几个关键参数:security = user 是 CentOS 7 默认的安全模式,要求每个连接先做用户认证,即使 guest 也要先经过 guest 账号映射。map to guest = Bad User 的含义是,如果客户端提交的用户名不存在,就把这个连接降级成 guest,这样匿名访问才能落进 guest account = nobody 的上下文。public 段里 path 指定实际目录,browseable = yes 让客户端在网络邻居里能看到此共享,writable = yes 允许写入,guest ok = yes 放行匿名访问。create mask 和 directory mask 是新建文件/目录时对系统权限按位取反掩码,这里让文件有 0664、目录有 0775,保证用户组可写。

启动两个服务并设置开机自启:

systemctl start smb nmb systemctl enable smb systemctl enable nmb

注意 CentOS 7 要用 systemctl,不要再用 service smb start 这种 SysV 命令。smb 服务对应 smbd(端口 445/139),nmb 服务对应 nmbd(UDP 137),负责 NetBIOS 名称广播解析,Windows 客户端靠它看到主机名。虽然很多教程说只开 smb 就行,但如果你想让 Windows 网络邻居里能列出主机,nmb 最好一起开。

之后用 testparm 验证配置语法,它会解析 smb.conf 并显示实际生效的参数:

testparm -s

如果输出里出现了你写的 [public] 段,说明配置至少没有语法错误。注意 testparm 只检查语法,不保证服务能通,真正的网络验证要等防火墙和 SELinux 配好,否则就算配置正确也会被拒之门外。在配置继续之前,也可以先用 smbclient -L 127.0.0.1 -U guest -N 看看本机是否能看到这个共享,如果这一步就失败,多半是服务没起来或配置写错了,别急着往后走。

3. 从匿名到认证共享:把 CentOS 7 目录安全地开放给同事

3.1 用户共享的设置流程:系统用户与 Samba 密码

匿名共享虽然方便,但任何能访问该网络的人都能下载甚至写入文件,稍一松懈就会变成“裸奔”。生产上给团队开目录,我会首选带用户认证的共享。Samba 的认证有个容易混淆的点:它要求客户端访问时提交的账号必须同时满足两个条件——账号存在于系统 /etc/passwd 中,并且在 Samba 的密码数据库中有记录。这两者不是一回事,系统密码是用户登录 Linux 用的,而 Samba 密码由 pdbedit 或 smbpasswd 管理。

创建用户的典型命令:

# 创建系统用户,不建家目录,禁止 SSH 登录 useradd -M -s /sbin/nologin shareuser # 添加该用户到 Samba 密码库,并设置 Samba 密码 pdbedit -a -u shareuser

pdbedit 是推荐做法,因为 CentOS 7 默认的 passdb backend 是 tdbsam,pdbedit 专门管理 tdbsam 数据库。执行后会交互式要求输入密码,这个密码和 /etc/shadow 里的系统密码无关。如果你出于习惯用 smbpasswd -a shareuser,它也可以,但 pdbedit 更统一。如果你希望一组人访问,建议创建同名系统组,比如 groupadd projectgroup,然后 useradd -G projectgroup user1。

需要提醒的是,-s /sbin/nologin 不影响 Samba 登录,因为 Samba 的认证不经过 shell,关掉 SSH 登录反而减少了攻击面。

3.2 配置认证共享:valid users、write list 与权限位

接下来在 smb.conf 里新增一个带认证的共享。我一般按业务建一个独立的段,例如 project:

[project] comment = Project Shared Files path = /srv/project browseable = yes read only = no valid users = @projectgroup, shareuser write list = @projectgroup create mask = 0660 directory mask = 0770 force group = projectgroup

这段配置比匿名共享多了三个关键项。valid users 限定能访问这个共享的用户或组,@projectgroup 代表项目组,其他人一律被拒;write list 指定额外可写成员,这表示即使用户能被读取,不在 write list 里也只能读不能写——我这里让整个项目组可写,所以 write list 和 valid users 很接近,但如果你想让某个人只读,比如经理,就不把他加进 write list。force group = projectgroup 很实用,它让所有在共享里创建的文件组属性强制为 projectgroup,避免用户各自的主组不一致,导致同组其他人无法写文件。

光改配置不够,系统目录本身要有正确的属主和权限:

mkdir -p /srv/project chown root:projectgroup /srv/project chmod 2770 /srv/project

chmod 的 2 是 setgid 位,它的作用是让该目录下新创建的文件自动继承 projectgroup 组。否则即使 Samba 做了 force group,新建的文件也可能因为用户的 umask 变成其他组,其他成员仍写不动。这一步是很多人配完 Samba 写不进文件的常见原因之一,后面避坑章节再展开。

改完配置后重启服务:

systemctl restart smb nmb

为什么用 restart 而不是 reload?因为新增共享段时,smbd 的主进程如果还持有旧配置,reload 也可能生效,但为了确保进程直接以新配置工作,特别是你改了 force group、create mask 这类会影响文件创建的参数,重启最稳妥。生产环境若怕中断连接,也可以 systemctl reload smb,测试机建议重启。

3.3 Windows 和 Linux 客户端分别怎么连接

Windows 客户端最直接的方式是按 Win+R 输入:

\\192.168.10.20\project

输入刚才创建的 shareuser 和 Samba 密码即可。如果 Windows 始终弹出“找不到网络路径”,先用 IP,不要依赖主机名,因为 NetBIOS 名称解析在跨 VLAN 时经常失效。要主机名可见,需要确保 nmb 服务开了,且 Windows 的 SMB 客户端功能正常。Windows 10/11 默认支持 SMB2/3,CentOS 7 的 Samba 4.x 也支持,两边默认协议能协商成功,不需要额外去“启用 SMB 1.0/CIFS 文件共享支持”。如果你是在 Windows 上测试的,反直觉结论是:往往越旧的方法越不管用。

Linux 客户端用 smbclient 验证最直接:

smbclient //192.168.10.20/project -U shareuser -W WORKGROUP

进去之后可以 ls、get 测试。也可以直接挂载成目录:

mkdir -p /mnt/project mount -t cifs //192.168.10.20/project /mnt/project \ -o username=shareuser,vers=3.0,uid=1001,gid=1001,iocharset=utf8

这里的 -o 参数里,vers=3.0 强制使用 SMB3 协议,避免某些旧内核模块回退到 SMB1 引发安全问题;uid/gid 指定挂载后的文件归属到本地账号,否则会显示成 root 占用,普通用户读不了;iocharset=utf8 处理中文文件名,防止乱码。如果你需要每次开机自动挂载,可以写进 /etc/fstab,但要用 credentials= 文件存放密码,避免把密码明文写进 fstab。

4. 打通防火墙和 SELinux:让 CentOS 7 的 Samba 真正可访问

4.1 防火墙放行 Samba:firewalld 三条命令

CentOS 7 默认开了 firewalld,它对网络接口按 zone 过滤。Samba 用了 TCP 139、445 和 UDP 137、138,firewalld 已经内置了 samba 服务别名,直接放行它就行:

firewall-cmd --permanent --add-service=samba firewall-cmd --reload firewall-cmd --list-services

第一条 --permanent 表示写入运行时配置并同时保存到磁盘,第二条 reload 让配置立即生效,第三条列出当前放行的服务,确认里面有没有 samba。注意 --reload 和 --complete-reload 的区别:前者保留运行时的手动规则,后者清空重新加载,日常用前者就够了。如果你图省事,也有很多人用 firewall-cmd --add-service=samba 不带 --permanent,结果机器一重启又失效——这种坑我踩过。

如果你的服务器是历史遗留,用了 iptables 而不是 firewalld,可以这样放行:

iptables -I INPUT -p tcp --dport 445 -j ACCEPT iptables -I INPUT -p tcp --dport 139 -j ACCEPT iptables -I INPUT -p udp --dport 137 -j ACCEPT iptables -I INPUT -p udp --dport 138 -j ACCEPT

但 CentOS 7 官方路径还是 firewalld,除非你明确停用了 firewalld,否则别混用,混用可能出现“一条 iptables 规则覆盖了 firewalld”的诡异情况。

4.2 SELinux 布尔值与上下文:两个 setsebool 一种做法

防火墙都通了,本机 smbclient -L 都能列共享,Windows 还是连不上,这时候十有八九是 SELinux。SELinux 对 Samba 的限制主要体现在两部分:布尔值和文件上下文。CentOS 7 默认开启 enforcing,smbd 程序域是 smbd_t,它要读取共享目录,共享目录必须被标记为 samba_share_t 类型,或者放开对应的布尔值。

最省事的做法是开全局写布尔值:

setsebool -P samba_export_all_rw on

这个布尔值让 smbd 可以读写所有被标记为 samba_share_t 或其他可导出类型的主机文件系统。但这相当于一把大门钥匙,粒度粗。更推荐按目录设置上下文:

semanage fcontext -a -t samba_share_t "/srv/project(/.*)?" restorecon -Rv /srv/project

第一条命令是向 SELinux 策略库注册一条规则,说明 /srv/project 目录及其子目录都应该用 samba_share_t 类型;第二条命令按当前策略重新给目录打标签,这样标签在重启或 restorecon 后依然有效。如果系统提示 semanage 命令不存在,安装 policycoreutils-python 包即可。

还有一种快速却临时的办法就是 chcon -Rt samba_share_t /srv/project,它直接改目录的上下文但不写入策略库,一旦磁盘重新标记或执行 restorecon 会恢复成原来的类型。我建议实验时可先用 chcon,确认问题后立刻补上 semanage + restorecon 让配置固化。

如果不确定当前是什么上下文,用 ls -Zd /srv/project 查看。显示 default_t 或 user_home_t 时,Samba 访问大概率会被拒。

4.3 验证服务监听与连接:ss、smbclient 的组合

配完防火墙和 SELinux,不要急着去 Windows 上点,先用服务器本机验证一条龙:

# 1. 检查端口监听 ss -tlnp | grep smbd ss -ulnp | grep nmbd # 2. 本机列出共享 smbclient -L //127.0.0.1 -U shareuser -W WORKGROUP

如果 ss 没有输出,说明 smbd/nmbd 进程没起来或者被系统限制了,用 systemctl status smb nmb 查看原因。如果端口正常但 smbclient -L 报 NT_STATUS_ACCESS_DENIED,排查认证和权限;如果报 connection refused,则大概率是防火墙或服务没起来,而不是 Samba 本身。

本机测试通过后,再找另一台 Windows 或 Linux 客户端连接。如果远程失败,检查远程到服务器的端口连通性,比如在另一台 Linux 上执行 nmap -p445 192.168.10.20,或 telnet 192.168.10.20 445。这时候出现的坑往往是跨网段、防火墙默认 drop,端口看起来通不了,就要回到 4.1 节去看 zone 配置了。

另外,如果本机能看共享但远程死活连不上,而且端口测试显示不通,先不要怀疑 Samba,直接看 firewalld 的 active zones:firewall-cmd --get-active-zones,确定你的网卡挂在哪一个 zone。很多时候服务器有内网和外网网卡,内网网卡挂在 internal zone,你在 public zone 放行了 samba,等于白做。这是配置防火墙时最容易漏掉的细节。

5. 实战中的 5 个翻车点:Samba 配置避坑排查指南

5.1 NT_STATUS_ACCESS_DENIED:目录权限还是 SELinux 的锅?

现象:smbclient 连上了共享,但执行 mkdir 或 put 时报 NT_STATUS_ACCESS_DENIED。

原因分两层。第一层是系统权限:Samba 在认证通过后,以该系统用户的身份去访问共享目录,如果目录不可写,即使 Samba 里 writable=yes 也无济于事。第二层是 SELinux:smbd_t 域被 SELinux 拒绝访问目标目录文件。这两者的现象完全一样,导致新手经常在 chmod 上折腾半天也没效果。

解决:先看目录属主、权限和上下文。一次做三件事:

ls -ld /srv/project ls -Zd /srv/project getsebool samba_export_all_rw

权限位建议目录至少 2770,属主组和 valid users 对应。上下文若不是 samba_share_t,按 4.2 节修复。如果是布尔值处于 off,setsebool -P samba_export_all_rw on。大部分情况下,前者是根因。注意顺序:先确认系统权限,再动 SELinux,因为 SELinux 的日志在 /var/log/messages 里会显示 avc: denied,更容易定位。

5.2 连接超时或拒绝:防火墙只开了 ssh 却忘了 samba

现象:Windows 双击服务器共享时一直转圈,最终报“找不到网络路径”或“错误 53”;Linux 客户端挂载时报 mount error(112) Connection refused。

原因:firewalld 只放行了 ssh,Samba 的 139/445 被默认 drop。Samba 服务名在 firewalld 里定义为 samba,不是 smb,新手容易敲 --add-service=smb,报错说服务不存在。

解决:按 4.1 节操作。如果自定义了非标准端口(生产不建议),要用 --add-port=1445/tcp 并改 smb.conf 里的 smb ports 参数。另有一种情况是客户端访问时走了 IPv6,但服务器 IPv6 防火墙不放行,可以在客户端用 -d 参数强制指定 IPv4,例如 mount -t cifs //192.168.10.20/share /mnt -o addr=192.168.10.20。

5.3 修改配置没有生效:restart 与 reload 的取舍

现象:在 smb.conf 里新增了共享,客户端用 smbclient -L 却看不到;或者改了 path,访问的还是老路径。

原因:smbd/nmbd 是常驻进程,启动时已经读入旧配置;很多教程只说“改完配置重启服务”,但有人在 testparm 看到新配置就以为生效了,testparm 只是静态解析,不代表运行中的进程已经切换。

解决:修改配置后,执行 systemctl restart smb nmb 让进程完全重启。如果只是改了权限相关参数而没有改共享结构,可以 systemctl reload smb,但对及时性没把握,我建议在维护窗口内统一 restart。重启后马上用 smbclient -L //127.0.0.1 -U shareuser 确认新的共享名出现。这里还要补一个习惯:改配置前用 cp 备份,改完用 testparm 检查语法再重启,避免一个语法错误让 Samba 起不来,客户端全部断开。

5.4 协议协商失败:老客户端连不上,日志提示 PROTOCOL_NEGOTIATION_FAILED

现象:老设备(例如生产仪器、老打印机或 Windows XP)连接时提示“无法连接”;服务器日志中出现 NT_STATUS_NOT_SUPPORTED 或 PROTOCOL_NEGOTIATION_FAILED。

原因:CentOS 7 自带的 Samba 4.10 默认 server min protocol = SMB2_10,这意味着低于 SMB2.1 的协议不会被接受。旧设备往往只支持 SMB1,而现代操作系统出于安全默认关闭 SMB1,两边无法协商。

解决:如果确认必须支持该设备,可在 [global] 设置 server min protocol = SMB1,并明确承担安全风险。SMB1 存在蠕虫和中间人攻击面,我不建议在公网或不可信环境这样做;如果是内网隔离且设备无法升级,可以用一个独立共享只给该设备使用,同时在防火墙里限制来源 IP。现代客户端不受影响,因为 server max protocol 默认为 SMB3,两者取交集。多数情况我会劝阻用户开启 SMB1,劝他用支持 SMB2 的新设备替代,不要让遗留设备拖累整台服务器的安全基线。

5.5 中文文件名乱码:客户端和挂载参数不对

现象:Windows 看共享文件的中文名变成“é”或问号;Linux 客户端用 CIFS 挂载后,中文文件名无法操作。

原因:Samba 服务端默认内部编码是 UTF-8,传输层走 unicode,大多数现代客户端没问题。乱码常见于挂载时未指定 iocharset,或者一些嵌入式客户端用本地编码,但本地编码不是 UTF-8。

解决:在 smb.conf 的 [global] 显式声明:

unix charset = UTF-8 display charset = UTF-8 dos charset = CP936

unix charset 和 display charset 保持 UTF-8,dos charset 让 Windows 侧传统代码页的客户端能正确解释。Linux 挂载时加 iocharset=utf8,例如 mount -t cifs //server/share /mnt -o username=user,iocharset=utf8。这里注意别把 dos charset 换成 GBK,否则本身用 UTF-8 的客户端反而乱。如果文件已经乱码,不要想在挂载层面挽救,那是当初写入时的编码不统一造成的,回头在源头整理,并约定全链路用 UTF-8。

6. 一条命令巡检 Samba 共享:验证连通性与写权限的更稳妥做法

前面的配置和排错都是基于手动测试,但生产环境需要一条可重复执行的命令,便于放进定时任务或根因排查。我最常用的是基于 smbclient 的写入探活,它不仅验证共享是否可见,还验证账户能不能真正写文件。分享一个可以直接套用的 bash 函数:

check_samba_share() { local srv=$1 local share=$2 local user=$3 local pass=$4 # 探活:列共享和目录 smbclient "//${srv}/${share}" -U "${user}%${pass}" \ -c "mkdir .healthcheck; rmdir .healthcheck" >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "[OK] ${srv} ${share} 可读写" else echo "[FAIL] ${srv} ${share} 连接或写入失败" fi } # 用法示例 check_samba_share 127.0.0.1 project shareuser 's3cret'

函数里的-c参数传给 smbclient 一条命令字符串,先创建再删除隐藏目录,模拟真实写入路径,不仅测网络连通,也测认证、SELinux、目录权限,一下子就暴露 5.1 节提到的 NT_STATUS_ACCESS_DENIED。如果只想测读,可以换成 ls。每次巡检后记住把退出码存下来,才算闭环。我一般还会追加一个 smbclient -L 看共享是否存在,但核心是写入探活,因为很多故障只影响写入而不影响读取。

如果你不想把密码明文放在命令行,可以搭配 --authentication-file= 或填入 credentials 文件,避免 shell 历史泄露。这个 shell 函数可以放入 /usr/local/bin/samba_health.sh,再交给 cron 每小时跑一次,输出追加到日志文件。我在早期运维生涯中吃过亏:平时共享能读、能列目录,就以为没事,直到月底别人汇报写不进文件才发现磁盘变成了只读,正是因为我没有做写入探活。从那以后,巡检统一要测 mkdir/rmdir,这个习惯帮我提前处理了好几次磁盘满或权限漂移的问题。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询