拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ubuntu Samba 公网文件共享:端口映射与权限对齐实战

Ubuntu Samba 公网文件共享:端口映射与权限对齐实战

手上有一台阿里云服务器,跑着几个内部服务,平时用它存一些日志归档、设计素材和给同事分发的安装包。最初的做法是 SFTP 上传下载,用了两个月实在受不了——同事要个 200MB 的素材包,得先下载到本地再传给别人,中间还要解释"你装个客户端"。后来换成对象存储,但每次生成分享链接、设置有效期又太琐碎。最后我决定在 Ubuntu 上装 Samba,把这些目录直接共享出来,Windows、macOS、Linux 三种客户端都能像访问本地磁盘一样双击打开。麻烦的地方在于,这是一台公网服务器,Samba 默认的 445 端口在公网上经常不通,于是又牵扯出端口映射、云平台安全组、系统防火墙这一整条链路。这篇就把从装包到跑通、从权限理清到排错收口的全过程写下来,Ubuntu 20.04/22.04/24.04 都适用,新手照着做能跑通,有经验的人可以重点看权限对齐和端口映射那两节。

1. 云服务器上跑Samba到底值不值:三个合适场景和两类劝退情况

1.1 从"上传下载"到"像本地磁盘一样用"

Samba 做的事说穿了很简单:在 Linux 上实现 SMB/CIFS 协议的服务端,让 Windows 的原生文件共享协议、macOS 的 Finder、Linux 的 cifs 内核模块都能挂上来。它和 SFTP、HTTP 下载最大的区别是挂载之后它是一个文件系统,而不是一个传输通道。这个差别带来的体验是量级的:你在 Windows 资源管理器里输入\\服务器IP\share,回车,输入一次账号密码勾选记住,之后这个目录就一直在"此电脑"里,双击打开、拖拽文件、右键新建文件夹、Office 直接"另存为"到这个路径,全部是原生操作。

我在实际使用中感受最深的是三类场景。第一类是团队内部的文件分发:设计稿、测试包、数据集,放到共享目录里,同事自己取,不用我反复发链接。第二类是跨设备同步工作目录:家里台式机、公司笔记本、虚拟机里的 Ubuntu,同一份代码草稿或者论文素材放在共享目录里,谁都能读写,省掉了 U 盘和聊天软件传来传去。第三类是给容器和虚拟机当"外挂盘":宿主机挂一个共享目录,虚拟机里mount -t cifs上去,改代码不用重启虚拟机,比共享文件夹方案更稳定。

这三类场景有个共同点:访问频率不高但单次文件不小,而且参与的人或设备只有几个。这正好落在 Samba 的舒适区里。如果你的场景偏离这个范围太远,下面这几种情况我建议先别折腾。

1.2 什么情况下我会劝你先别装Samba

第一种是只需要单向读取、几乎没有写入。比如你只是想给一个静态资源目录做个下载入口,那用 Nginx 的autoindex或者对象存储更省事,Samba 的账号体系、端口、防火墙配置一整套下来,成本明显更高。

第二种是多人高频并发写同一个文件。SMB 有文件锁机制,但它是为"一个人打开一份文档编辑"设计的,不是为"五个人同时往一个文件里追加日志"设计的。数据库文件、Git 仓库的.git目录、正在被编译的构建产物,都不要放在 Samba 共享里直接操作,你会遇到文件锁冲突、写入不完整、甚至索引损坏。这类需求应该走版本控制或者专门的同步工具。

第三种最需要说清楚:敏感数据不要裸奔在公网。Samba 老版本默认允许 SMB1、允许匿名访问,这些默认值在公网上就是风险敞口。如果确实要公网访问,那必须走非标准端口、强制 SMB3 加密、账号强密码、安全组限定源 IP 这一整套收口动作,具体在第八节展开。

2. 动手前的环境盘点:Ubuntu版本、网络出口和云平台安全组

2.1 三条命令把家底摸清

在敲apt install之前,我习惯先把三件事确认一遍,这三件事任何一件不对,后面都会白折腾。

# 系统版本与内核 lsb_release -a uname -r # 网卡与内网地址 ip -4 addr show # 当前对外出口地址(确认公网 IP 是弹性 IP 还是 NAT 出口) curl -s ifconfig.me; echo

lsb_release -a看的是发行版版本,Ubuntu 20.04 自带 Samba 4.11,22.04 是 4.15,24.04 是 4.19,这几个版本的配置文件语法基本兼容,但 24.04 在默认协议上更严格,老客户端如果只支持 SMB1 会直接连不上,这一点后面会细说。

ip -4 addr show输出的地址很关键:阿里云 ECS 的网卡上看到的一般是内网地址(10.x、172.16.x 段),公网 IP 是通过 NAT 映射到这张网卡上的。这意味着 Samba 配置里不要写死公网 IP,interfaces和bind interfaces only这类参数能不写就不写,让它默认监听所有地址最省心。

2.2 阿里云安全组:公网访问绕不过去的第一道门

这是新手最容易卡住的地方:服务明明起来了,systemctl status smbd一片绿,本机smbclient也能连上自己,但外网死活连不上。九成以上的原因在安全组。

阿里云的入方向规则是按协议 + 端口范围 + 授权对象三个维度配的。你需要开的是:

协议端口用途授权对象建议
TCP445SMB over TCP,现代 Windows/macOS 首选自己的固定出口 IP/32
TCP139老客户端走 NetBIOS over TCP 时用同上,不用可不加
UDP137-138NetBIOS 名称解析,仅局域网式广播场景需要一般不用加
TCP4450自定义映射端口(示例)自己的固定出口 IP/32

授权对象那一栏我要多说两句。很多人图省事填0.0.0.0/0,等于把共享目录挂到全世界面前。只要有一台机器被扫到,弱口令爆破是几小时内的事。正确做法是填自己家的宽带出口 IP 加/32,公司如果也是固定出口就再添一条。/32 的意思是这个地址段里只有这一个 IP,比填一个 C 段安全得多。宽带的公网 IP 会变,隔段时间连不上就回来改一下,这个麻烦值得吃。

2.3 系统防火墙:ufw 和 firewalld 的选择

Ubuntu 默认装的是 ufw,但默认状态是未启用(inactive)。这里有个取舍:

  • 只用安全组,不开 ufw:配置最省事,但安全组一旦被人误改,主机就完全没有第二道防线。
  • 两者都开:安全组做粗粒度控制,ufw 做主机层面的细粒度控制,我推荐这个方案。

ufw 的放行写法注意要用 Samba 的应用配置文件,它会一次性把该放的端口放对:

ufw allow from 203.0.113.10 to any port 4450 proto tcp ufw allow Samba ufw status verbose

第二条ufw allow Samba会自动套用/etc/ufw/applications.d/samba里的定义,把 137/138/139/445 一起放行。如果你改成了自定义端口 4450,那就用第一条那种显式写法,别依赖应用配置文件。

注意:ufw 默认会拒绝所有入站,所以在ufw enable之前一定确认 SSH 的 22 端口已经放行,否则会把自己关在门外。云服务器上这一点比本地机器更要命,因为控制台的 VNC 救援入口操作起来很别扭。

3. 安装Samba与最小可用配置的落地过程

3.1 apt 安装与版本确认

安装本身一行命令,但后面的确认步骤别省:

sudo apt update sudo apt install -y samba samba-common-bin smbd -V systemctl status smbd --no-pager

smbd -V打印的是实际生效的版本号,比apt policy samba更可信。安装过程会自动生成一份/etc/samba/smb.conf默认配置,同时创建smbd和nmbd两个 systemd 服务。这里有个细节:Ubuntu 上 smbd 和 nmbd 是分开的两个 unit,你在局域网里靠"网络邻居"浏览共享依赖 nmbd,但如果是通过\\IP\share直接访问,其实只用 smbd 就够了。我一般两个都留着。

systemctl status smbd显示active (running)就说明服务起来了,但这只是"能启动",不代表"能连上",配置对不对还得看下一节。

3.2 smb.conf 的结构:global 段管全局,共享段管目录

/etc/samba/smb.conf的语法非常朴素,只有两种东西:节(section)和参数(parameter)。节用方括号包起来,[global]是唯一有特殊地位的节,里面的参数作用于整个服务;其他节名就是共享名,客户端看到的就是这个名字。

注释支持#和;两种,但有个坑要提:参数值里的;和#也会被当成注释起始符,比如你在某个路径里带了#,会被截断。所以路径里尽量别用这两个符号。

另外推荐一个组织方式,从 Samba 4.0 起官方配置末尾就有这几行:

include = /etc/samba/smb.conf.%U include = /etc/samba/smb.conf.%G

%U是登录用户名,%G是用户主组。这意味着你可以给每个用户单独放一份覆盖配置,把个性化的东西(比如专属目录)写在/etc/samba/smb.conf.zhangsan里,主配置保持干净。团队人多的时候这个机制非常好用,主配置只用管公共共享。

3.3 一份能跑起来的最小配置

下面这份配置我用了很久,思路是"先把只读共享跑通,再逐步加可写共享":

[global] workgroup = WORKGROUP server string = Cloud File Server security = user map to guest = never server min protocol = SMB2_10 client min protocol = SMB2_10 unix charset = UTF-8 dos charset = CP936 log file = /var/log/samba/log.%m max log size = 1000 logging = file log level = 1 [public] comment = Public Read Only path = /srv/samba/public browseable = yes read only = yes guest ok = no valid users = @smbusers create mask = 0644 directory mask = 0755 [team] comment = Team Writable Share path = /srv/samba/team browseable = yes read only = no guest ok = no valid users = @smbusers write list = @smbusers force group = smbusers create mask = 0660 directory mask = 2770

几个参数值得单独解释。server min protocol = SMB2_10是为了关掉 SMB1——SMB1 是 1980 年代的协议,存在大量已知问题,现在的 Windows 10/11 和 macOS 都已经默认不使用了,关掉它没有任何体验损失,只是防止古董设备接入。map to guest = never是彻底禁止匿名访问,任何没有正确凭据的连接直接拒绝,不给它降级成 guest 的机会。

unix charset = UTF-8和dos charset = CP936这对组合是解决中文文件名的。Unix 侧文件名是 UTF-8 存储的,老 Windows 客户端在协商时可能用 GBK 编码,dos charset = CP936让服务端在必要时做转换。新版 Windows 基本都走 UTF-8 了,这个参数留着不碍事。

3.4 改完配置必须跑 testparm

这是我这几年养成的肌肉记忆,比重启服务还重要:

testparm -s

它会做两件事:一是检查语法,二是把最终生效的配置(含所有默认值)打印出来。很多人以为自己的配置生效了,其实某个参数写错位置被忽略了——比如把read only写进了[global],它不会报错,但也完全不起作用。testparm -s的输出里能看到这个参数到底有没有落到对应的共享段里。

改完配置不重启也能生效,用这个命令通知 smbd 重载:

sudo smbcontrol all reload-config

只有改动smb ports、interfaces这类监听层面的参数时,才必须systemctl restart smbd nmbd。

4. 账号与权限的三方对齐:系统用户、Samba用户、目录归属

这一节是整篇里最容易让人栽跟头的地方,我见过太多人卡在这里。核心原因是:访问一个共享目录,要同时过两套体系的检查。

4.1 为什么系统用户建好了还是登录失败

Samba 用的是 Linux 的系统用户来做身份映射,但密码库是独立的。你useradd建了用户、设了系统密码,Samba 完全不认——它查的是/var/lib/samba/private/passdb.tdb(老版本在/etc/samba/smbpasswd)。所以必须再用smbpasswd -a往 Samba 的密码库里加一份。

顺序上我建议这样:

sudo adduser zhangsan # 建系统用户,会同时建同名组 sudo smbpasswd -a zhangsan # 设置 Samba 密码,交互式输入 sudo smbpasswd -e zhangsan # 确保账号是启用状态 sudo pdbedit -L # 列出所有 Samba 用户

pdbedit -L是排查时的第一手工具,输出了用户名和 UID 说明注册成功;如果这里没有你要的用户,那前面smbpasswd -a一定失败了,去看它的报错。

4.2 smbpasswd 的几个常用动作

命令作用使用时机
smbpasswd -a user添加并设置密码首次创建 Samba 用户
smbpasswd -e user启用账号账号被 -d 禁用后恢复
smbpasswd -d user禁用账号人员离职、临时停用
smbpasswd -x user删除 Samba 用户彻底移除(不动系统用户)
smbpasswd user修改自己的密码普通用户自助改密
pdbedit -L -v查看详细账号信息排查账号状态

-d和-x的区别值得记住:-d只是标记禁用,随时能-e回来;-x是从密码库里删掉,重新加要重设密码。人员流动频繁的团队,-d更灵活。

4.3 目录权限、create mask 与 force user 的配合

现在说最难的一层:文件系统权限。Samba 拿到登录用户后会切换到对应的 Linux 用户身份去读写目录,所以目录的属主、属组、权限位必须允许这个用户操作。

这里有三组概念容易混:

  • 目录本身的权限(ls -ld /srv/samba/team看到的drwxrws---):决定用户能不能进这个目录、能不能在里面创建文件。
  • create mask / directory mask:决定新建的文件和子目录的权限位。注意它只是"允许的最大权限",实际权限还会受 umask 影响,Samba 用的是"请求权限 AND mask"的逻辑。
  • force user / force group:强制所有操作以指定的用户或组身份进行,忽略客户端的实际登录身份。

force group是最实用的一个。团队共享目录配上force group = smbusers和create mask = 0660,不管谁来创建文件,文件的属组都是smbusers,组内成员都能读写,不会出现"张三建的文件李四改不了"这种事。

directory mask = 2770里的那个2是SGID 位,它保证在这个目录里新建的子目录自动继承父目录的属组,而不是继承创建者的主组。没有这个位,子目录的属组会变成创建者的默认组,共享结构一深入就全乱了。

4.4 几种常见共享形态的权限方案对照

不同用途的共享目录,权限配法差别很大,我整理成一张表:

共享形态目录权限关键参数说明
个人私有目录drwx------属主自己valid users = %U、read only = no每人一个目录,互不可见
团队可写目录drwxrws---属主 root:smbusersforce group = smbusers、create mask = 0660、directory mask = 2770组内全员读写,推荐
只读分发目录drwxr-x---属主 root:smbusersread only = yes、valid users = @smbusers管理者单独留写权限
投递目录(只进不出)drwx-wx---属主 root:smbusersread only = no、write list = @smbusers配合目录无读权限收集作业、上传文件,防止互相偷看

最后那个"投递目录"值得说一下。给目录设成drwx-wx---(有写无读),用户能往里扔文件但看不到目录里有什么,配合create mask = 0600让上传的文件只有自己能读。这个模式在收集报表、作业、匿名反馈的场景里非常实用,但要注意用户重复上传同名文件时会失败(因为他看不到已存在的文件,却也没权限覆盖),通常要在客户端加时间戳后缀。

目录创建和权限设置的具体命令:

sudo mkdir -p /srv/samba/{public,team,drop} sudo groupadd smbusers sudo usermod -aG smbusers zhangsan sudo usermod -aG smbusers lisi sudo chown root:smbusers /srv/samba/team sudo chmod 2770 /srv/samba/team sudo chown root:smbusers /srv/samba/public sudo chmod 2750 /srv/samba/public

改完组关系后,已经登录的会话不会自动获得新组,要么让用户重新登录,要么用newgrp smbusers刷新。这是排查"我明明加了组怎么还是不行"的经典原因。

5. 端口映射实战:把445换成自定义端口打通公网

5.1 为什么公网直连445经常不通

445 端口在公网上的处境很特殊。历史上有多轮大规模的网络蠕虫利用了 SMB 服务的漏洞传播,导致运营商和云平台普遍对 445 做了出入方向的限制。你在家里宽带试,很可能出方向的 445 是直接被拦掉的,表现就是 TCP 握手根本建立不起来,telnet 服务器IP 445一直卡在连接中,而不是快速拒绝。

这种情况下的解决办法就是换一个非标准端口,把 SMB 服务监听在你指定的端口上,然后通过云平台安全组把这个端口映射放行出去。严格说这叫"端口变更 + 安全组放行",云平台的 NAT 网关完成内外网地址的转换,你不需要在阿里云上做额外的 DNAT 配置——安全组放行 + 服务改端口这两步就够了。

5.2 用自定义端口映射的完整配置链

四步,顺序很重要:

# 第一步:改服务监听端口 sudo vi /etc/samba/smb.conf # 在 [global] 段加上: # smb ports = 4450 # 第二步:防火墙放行(只给自己出口 IP) sudo ufw allow from 203.0.113.10 to any port 4450 proto tcp # 第三步:重启服务并验证监听 sudo systemctl restart smbd nmbd ss -lntp | grep -E '445|4450' # 第四步:云控制台安全组入方向添加 TCP 4450 规则

ss -lntp的输出是判断成败的关键:应该只看到 4450 在监听,445 消失了。如果两个都在,说明配置没生效或者被别的地方覆盖了,回去跑testparm -s | grep smb\ ports确认。

改端口有个连带影响要提前说:smb ports改了以后,NetBIOS 那一套(137/138/139)实际就废了,靠"网络邻居"自动发现的方式不再工作。这不算问题,因为公网环境本来也不该用广播发现,直接用\\IP:端口\共享名这种显式路径访问更可靠。

5.3 客户端怎么指定端口

这是改端口之后最麻烦的一环,因为不同客户端的支持程度差别很大:

客户端指定端口的方式是否原生支持
smbclient-p 4450或--port=4450支持
Linux mount.cifs挂载选项port=4450支持
macOS Findersmb://IP:4450/share支持
Windows 资源管理器不支持需本地端口转发

Linux 端的实测写法:

# 先探测共享列表 smbclient -L //203.0.113.10 -p 4450 -U zhangsan # 临时挂载 sudo mkdir -p /mnt/team sudo mount -t cifs //203.0.113.10/team /mnt/team \ -o port=4450,username=zhangsan,uid=$(id -u),gid=$(id -g),\ file_mode=0660,dir_mode=2770,iocharset=utf8,vers=3.0 # 查看挂载状态 mount | grep cifs

vers=3.0这个选项建议显式写上。老内核默认可能协商到 SMB1,而我们在服务端已经关掉了 SMB1,结果就是挂载时报一个很含糊的协议不匹配错误。写死3.0或3.1.1能省掉一堆排查。

5.4 Windows 客户端在非标准端口下的处理

Windows 资源管理器在地址栏输\\IP:4450\share是不认的,它会报"找不到网络路径"。绕过去的办法是在本机做一个本地端口转发,把本地的 445 映射到服务器的 4450,然后访问\\127.0.0.1\share:

:: 以管理员身份运行 netsh interface portproxy add v4tov4 listenport=445 listenaddress=127.0.0.1 connectport=4450 connectaddress=203.0.113.10 :: 查看已配置的转发 netsh interface portproxy show all :: 删除 netsh interface portproxy delete v4tov4 listenport=445 listenaddress=127.0.0.1

这里的关键点是listenaddress=127.0.0.1。Windows 自身的 SMB 服务已经占用了 0.0.0.0:445,如果你监听地址写0.0.0.0,转发规则会添加失败或者不生效。绑定在回环地址上就避开了这个冲突,代价是只能本机访问,对本机映射驱动器来说完全够用。

顺手提醒:端口转发规则是持久化的,重启后仍然存在。如果哪天服务器 IP 变了或者不用了,记得回来delete,否则会出现连到老地址的超时等待,非常难排查。

6. 三种客户端的接入方式与各自的小脾气

6.1 Windows:映射网络驱动器与凭据管理

Windows 端的标准流程是这样:打开"此电脑",右键"映射网络驱动器",文件夹框填\\203.0.113.10\team,勾选"使用其他凭据",输入 Samba 用户名密码,勾选"记住我的凭据"。也可以用命令行一次搞定:

net use Z: \\203.0.113.10\team /user:zhangsan * /persistent:yes net use net use Z: /delete

/persistent:yes让它在重启后自动重连,*表示交互式输入密码,避免密码留在命令历史里。

Windows 这边有几个特有的坑。一是凭据冲突:如果你之前用另一个账号连过同一台服务器,Windows 会缓存旧凭据,新账号怎么输都失败,报"多重连接到一个服务器或共享资源"或者直接认证失败。清理方式是在"凭据管理器"里删掉对应的 Windows 凭据,或者用net use * /delete全部断开重来。二是访客访问策略:较新的 Windows 版本默认禁止用 guest 身份做 SMB 访问,如果服务端配了允许 guest 的共享,客户端可能直接拒绝连接,报错代码往往是0x8007052e之类。这也是我一直建议关掉 guest 的原因之一——两边策略不一致会制造很多无谓的排错时间。

6.2 macOS:Finder 的 smb:// 和它在共享目录里留下的垃圾

macOS 接入很简单,Finder 里按Cmd + K,输入smb://203.0.113.10:4450/team,认证后就会挂载到/Volumes/team。命令行方式:

mkdir -p ~/mnt/team mount_smbfs //zhangsan@203.0.113.10:4450/team ~/mnt/team umount ~/mnt/team

macOS 有两个特别烦人的行为。第一是它会在每个目录写.DS_Store元数据文件,在共享目录里一样照写不误,几个月下来目录里全是隐藏文件。第二是在复制包含扩展属性的文件时生成._前缀的伴生文件(AppleDouble 格式),你的服务器目录会被这些文件撑得很难看。

解决办法是在共享段加上过滤:

veto files = /._*/.DS_Store/ delete veto files = yes

veto files让服务端直接隐藏这些文件,客户端看不到也写不进去;delete veto files = yes表示删除目录时允许连带删掉被 veto 的文件。这个改动很小,但共享目录的整洁度提升非常明显。

6.3 Linux:cifs-utils 与开机自动挂载

Linux 端的准备工作是先装上工具包:

sudo apt install -y cifs-utils

然后把凭据单独放一个文件,避免密码出现在/etc/fstab这个全局可读的地方:

# /etc/samba/cred-team,权限设成 0600 sudo tee /etc/samba/cred-team > /dev/null <<'EOF' username=zhangsan password=你的密码 domain=WORKGROUP EOF sudo chmod 600 /etc/samba/cred-team

对应/etc/fstab里的写法:

//203.0.113.10/team /mnt/team cifs credentials=/etc/samba/cred-team,port=4450,vers=3.0,uid=1000,gid=1000,file_mode=0660,dir_mode=2770,iocharset=utf8,_netdev,noauto,x-systemd.automount 0 0

这里几个挂载选项各有讲究。_netdev告诉系统这是网络文件系统,等网络就绪后再挂载,不加的话开机时可能因为网络还没起来而挂载失败,进而卡住整个启动流程。noauto表示不随mount -a自动挂载。x-systemd.automount让 systemd 创建一个自动挂载点,第一次访问该目录时才真正去挂载。这个组合是我目前最推荐的:既避免了开机网络竞态,又不需要手动敲 mount。

7. 连不上、能读不能写:按层排查的完整链路

排错最忌讳的是到处乱改配置。我的做法是固定按四层顺序走,每层都有明确的验证命令,确认通过再进下一层。

7.1 第一层:网络层,先确认端口能通

# 从客户端测 nc -vz 203.0.113.10 4450 telnet 203.0.113.10 4450 # 服务器上看监听状态 ss -lntp | grep smbd

如果这一层就不通,问题不在 Samba,而在安全组或者 ufw。判断技巧是看报错形态:Connection refused说明包到了服务器但没服务监听,方向是查 smbd;超时卡住Connection timed out说明包被中间设备丢了,方向是查安全组和运营商策略。这两个报错指向完全不同的原因,别混着查。

7.2 第二层:服务层,本机连自己

smbclient -L //127.0.0.1 -p 4450 -U zhangsan smbstatus

smbclient -L能列出共享名,说明服务本身和配置没问题。这一步通过但外网不通,就回到第一层继续查网络。smbstatus更有意思,它能看到当前所有活跃连接、锁定的文件、以及每个连接的登录用户,排查"谁占着文件不放"的时候非常有用。

7.3 第三层:认证层,用目标账号实测

smbclient //203.0.113.10/team -p 4450 -U zhangsan # 进入交互后 smb: \> ls smb: \> put /etc/hostname test.txt

这一步是分水岭。如果ls成功但put失败,问题在权限层,跟认证无关。如果登录就失败,检查pdbedit -L里有没有这个用户、账号是不是启用状态、密码是不是搞错了大小写。

7.4 第四层:权限层,从文件系统角度复验

ls -ld /srv/samba/team sudo -u zhangsan ls -l /srv/samba/team sudo -u zhangsan touch /srv/samba/team/.perm_test && echo OK

最后那条命令是我最爱用的招数:绕开 Samba,直接用目标系统用户的身份去写文件。如果这一步都写不进去,那 Samba 怎么配都没用,是纯文件系统权限问题;如果这一步能写,但通过 Samba 不行,那就是read only、write list、create mask这些 Samba 参数的问题。

7.5 常见报错对照表

客户端现象大概率根因验证方式
连接超时,无任何提示安全组未放行 / 端口写错nc -vz IP 端口
Connection refusedsmbd 未运行或未监听该端口ss -lntp | grep smbd
提示用户名或密码错误Samba 密码未设置 / 账号被禁用pdbedit -L、smbpasswd -e
能看到共享名但点进去报无权限valid users不含该用户或组关系未刷新testparm -s、重新登录
能读不能写read only = yes/write list限制 / 目录权限不足用sudo -u复验写权限
Windows 报多重连接错误客户端旧凭据冲突凭据管理器清理、net use * /delete
中文文件名乱码字符集参数缺失检查unix charset与客户端编码
大文件传到一半中断会话超时 / MTU 问题deadtime、socket options调整

7.6 日志在哪里、怎么开更详细的日志

Samba 的日志默认在/var/log/samba/下,log.%m这个写法会让每个客户端 IP 生成一个独立文件(%m是客户端机器名,实际文件名可能是log.203.0.113.10或者log.desktop-abc)。查的时候先ls -lt /var/log/samba/找最新的那个。

排错时需要临时提高日志级别:

# [global] 段 log level = 2

级别 2 会把认证过程、权限检查的关键路径打出来,足够定位绝大多数问题。但排完必须改回 1,级别 3 以上会让日志文件飞速膨胀,几天就能吃掉几个 G 的磁盘,我见过因为这个把系统盘写满导致服务全挂的情况。

8. 挂在公网上的Samba:安全收口与并发调优

8.1 认证层面的几道闸必须先关

公网暴露的服务,安全配置不能靠"应该没人会扫到"。我在[global]段固定加这几行:

security = user map to guest = never guest account = nobody restrict anonymous = 2 server min protocol = SMB2_10 smb encrypt = required obey pam restrictions = yes pam password change = yes

smb encrypt = required是这里面最有分量的一条,它强制所有 SMB3 流量加密。这个参数只在 SMB3 下有效,这也是为什么前面要强制server min protocol = SMB2_10——老协议不支持加密,必须一起调。开启加密后有轻微的性能开销,但在公网传文件,这点开销必须接受。

restrict anonymous = 2是彻底拒绝匿名连接,连共享列表都不给匿名用户看。obey pam restrictions = yes让 Samba 遵循系统的账号策略,比如账号锁定规则、密码过期时间,这些在纯 Samba 层是管不到的。

8.2 网络层面的收口手段

除了前面说的安全组限定源 IP,还有两个做法:

一是不用标准端口。这不算真正的安全措施(端口扫描一样能发现),但能过滤掉大量只会扫 445 的自动化脚本,降低被盯上的概率。

二是给认证失败加限制。可以用 fail2ban 监控 Samba 日志里的认证失败记录,连续失败达到阈值就把源 IP 临时封禁:

sudo apt install -y fail2ban # 新建 /etc/fail2ban/jail.d/samba.conf
[samba] enabled = true port = 4450 filter = samba logpath = /var/log/samba/log.%m maxretry = 3 bantime = 3600 findtime = 600

配置完之后sudo fail2ban-client status samba能看当前的封禁列表。这个组合对暴力破解的效果非常明显,实测下来配上之后日志里的异常尝试会大幅减少。

8.3 性能与稳定性参数

公网传输的两个主要瓶颈是带宽和单连接延迟。Samba 默认的一些参数是为局域网优化的,公网环境下可以调:

socket options = TCP_NODELAY IPTOS_LOWDELAY read raw = yes write raw = yes aio read size = 16384 aio write size = 16384 deadtime = 15 keepalive = 60

TCP_NODELAY关掉 Nagle 算法,减少小请求的延迟累积,交互式操作(列目录、打开小文件)体感提升明显。deadtime = 15表示连接空闲 15 分钟就断开,释放服务端资源,避免大量僵尸连接堆积。keepalive = 60每 60 秒发一次探测包,防止中间的 NAT 设备把空闲连接表项回收——这是大文件传输中途断掉的常见原因。

aio read/write size开启异步 IO,大文件顺序读写会有一定提升。但如果你的服务器磁盘本身是云盘、IOPS 有限,这个参数的收益不大,不要指望它能突破磁盘瓶颈。

关于带宽还有个现实提醒:阿里云 ECS 的公网带宽是按购买量计的,如果你买的是 5Mbps 带宽,理论峰值也就 600KB/s 左右,传 1G 的文件要将近半小时。这个跟 Samba 配置没关系,是链路本身的限制。要传大文件要么提带宽(贵),要么走内网(同地域的机器走内网地址,带宽和速度完全是另一个量级)。

9. 我在实际部署里踩过的坑和留下的几个习惯

第一次部署的时候,我在改完smb.conf后忘了重启服务,然后对着smbclient报了半小时的"用户名或密码错误"——因为服务还在用旧配置,而我新加的用户根本不在旧配置的valid users里。从那以后我的固定动作是:改配置 →testparm -s→smbcontrol all reload-config或systemctl restart smbd nmbd→smbstatus确认。这四个动作连成一条肌肉记忆,能省掉大量无意义的调试。

第二个坑是中文文件名。早期配置里只写了unix charset = UTF-8,Windows 客户端传上来的中文文件名在 Linux 侧看是乱码。补上dos charset = CP936之后正常了。后来发现新版 Windows 走 UTF-8 协商就没这个问题,但为了兼容一些老设备,这个参数一直留着。

第三个坑是磁盘写满。有一次开了log level = 3排一个问题,排完忘了改回来,一周后 smbd 突然拒绝服务,查了半天发现是日志目录把系统盘写满了。Samba 的日志级别是排查工具,不是常驻配置,这是我现在写在部署清单第一条的话。

第四个坑是关于force user的误解。我一开始以为配了force user就能无视目录权限,结果发现不是——force user只是切换身份,切换后仍然受该用户对目录的权限约束。如果被强制切换的那个用户对目录没有写权限,照样写不进去。这个理解纠正之后,我在配force user时会同时检查那个用户对目标目录的权限。

最后留下几个习惯,都是被坑出来的:部署完成后立刻把可用的smb.conf备份到/etc/samba/smb.conf.bak.$(date +%F),改坏了随时回滚;目录结构固定用/srv/samba/做根,不散落在/home里,因为/home在有些发行版上有自动挂载和配额策略,会给共享带来额外变量;客户端的凭据文件权限永远设成 0600,服务器上的passdb.tdb也只在备份时导出,不往代码仓库里放。

这套方案我在几台阿里云 ECS 上跑了两年多,日常就三五个人的使用强度,除了偶尔要更新一下安全组里的源 IP(家里宽带换地址了),基本没出过需要紧急处理的问题。真正花时间的从来不是安装那一步,而是把权限、端口、防火墙这三层对清楚,以及养成改配置后验证的习惯。

返回列表