跳转至

Samba 文件共享部署 SOP(dell-R620)

实现体:samba_ins/ Python 部署工程(main.py + deployer.py + utils/) 配置源:config/samba_deploy.yaml 本文第 5 章为等价操作序列,供人阅读与手工复核;幂等、备份与回滚一律以实现体为准。


1. 背景

Windows 工作站需要读写 dell-R620(Ubuntu 24.04.3 LTS)上的 /home/rain/Documents,用于日常文件交换与工程交付。

变更前实测状态:

  • 未安装 Samba 服务端,仅有客户端库(cifs-utils、libsmbclient0、samba-libs)
  • 无 /etc/samba 目录,无 smbd.service
  • 445 / 139 端口空闲,无进程占用
  • 主机未启用任何防火墙(ufw 未激活、firewalld inactive、iptables INPUT 策略 ACCEPT)

因此这是一次首次部署,而非配置变更。

2. 目标

变更完成后应达到的可验证状态:

  1. smbd、nmbd、wsdd 三个服务均为 active 且 enabled
  2. 445 / 139 (TCP) 仅监听 192.168.31.249(br0),不再监听 0.0.0.0
  3. 137 / 138 (UDP) 由 nmbd 提供;3702 (UDP) 由 wsdd 提供(含组播 239.255.255.250)
  4. Samba 账号 smbuser 可通过认证,且对 /home/rain/Documents 具备读、写、可遍历权限
  5. Windows 侧可通过 \\192.168.31.249\Documents 读写文件
  6. 敏感目录 .trae、.idea、.git、.env、.venv、.vscode 对客户端不可见且不可访问
  7. 连续执行两次,第二次零变更、全跳过

3. 前置条件

项 要求 实测
执行权限 当前账号具备免密 sudo rain 属 sudo 组,sudo -n true 成功
软件源 apt 源可用 cn.archive.ubuntu.com + security 可达,samba 候选 2:4.19.5+dfsg-4ubuntu9.7
共享目录 已存在且为目录 /home/rain/Documents,2.4G,属主 rain:rain,初始权限 755
端口 445/139 无占用 空闲
磁盘余量 ≥ 1GB / 剩 163G,/data 剩 1.7T
密码来源 环境变量 SMB_PASSWORD 禁止写入任何文件或脚本
网络可达 Windows 与 192.168.31.249 二层可达 Windows 侧 ping 通,TTL=64

所需工具(由工程 venv 提供,不装进系统 Python):Python ≥ 3.9、PyYAML、paramiko;共享库 /home/rain/py_public_modules 经 .pth 引入。

4. 影响范围

  • 主机:dell-R620 单台。单主机变更,无冗余节点,出问题没有其他节点可顶替,故第 6、7 章按最坏情况写实。
  • 新增组件:软件包 samba、wsdd、smbclient;系统账号 smbuser(无家目录、/usr/sbin/nologin,附加组 rain);systemd unit /etc/systemd/system/wsdd.service(Ubuntu 官方 wsdd 包不含 unit,由本工程维护)。
  • 覆盖的文件:/etc/samba/smb.conf(覆盖前带时间戳备份)。
  • 权限变更:/home/rain/Documents 由 755 → 775(补组写位,使 rain 组成员 smbuser 可写)。原权限记录于 logs/share_permission_before(内容 755 rain:rain),仅改本目录权限位,不改属主、不改上级目录。
  • 是否停服:不停服,不重启系统。仅在配置变更时对 smbd/nmbd 执行 restart(秒级中断);变更时无客户端连接,实际无感。
  • 同机其它业务:本机是 KVM 宿主,运行 openwrt + k8s 三控三节点共 7 台虚机,另有 Docker。本变更不触碰 netplan / 网桥 / 路由 / sysctl / iptables,对虚机与 k8s 无影响。
  • 窗口期:无需专门窗口。建议避开 Windows 侧正在传输大文件的时段。
  • 新增端口暴露:445/139 (TCP)、137/138 (UDP)、3702 (UDP),均仅绑定 br0;无主机防火墙,同网段主机可探测到这组端口。

5. 分步操作

对应实现文件:main.py(入口)、deployer.py(SambaDeployer,生命周期与方法见下) 以实现体为准:以下为等价手工序列,不承担幂等与错误处理;幂等、备份、回滚由工程实现。

5.1 触发部署

cd /home/rain/Documents/samba_ins                              # 进入工程目录
.venv/bin/python -m py_compile main.py deployer.py utils/*.py   # 语法自检,失败则不进入下一步
.venv/bin/python main.py --config config/samba_deploy.yaml --dry-run   # 预演:只输出待变更项,不改系统

SMB_PASSWORD='***' DEBIAN_FRONTEND=noninteractive \
  .venv/bin/python main.py --config config/samba_deploy.yaml    # 正式部署(密码经环境变量传入,不落盘)

5.2 实现体实际执行的系统动作

sudo apt-get install -y samba wsdd smbclient        # 装包;已安装的包由 dpkg-query 判定后跳过
sudo useradd --no-create-home --shell /usr/sbin/nologin --groups rain smbuser   # 建专用账号;已存在则跳过
sudo smbpasswd -s -a smbuser                        # 设 Samba 密码:经 stdin 传两遍,不进命令行、不落盘
sudo chmod g+w /home/rain/Documents                 # 补组写位(原 755 记录于 logs/share_permission_before)
sudo install -m 0644 -o root -g root <tmp> /etc/samba/smb.conf   # 【高危】覆盖配置;覆盖前已备份 smb.conf.bak.<时间戳>
sudo install -m 0644 -o root -g root <tmp> /etc/systemd/system/wsdd.service  # 写 wsdd unit(官方包不含)
sudo systemctl daemon-reload                        # 使新 unit 被 systemd 识别
sudo systemctl enable smbd nmbd wsdd                # 设开机自启;已 enabled 则跳过
sudo systemctl restart smbd nmbd                    # 载入新配置(仅配置有变更、或仍以通配地址监听时执行)
sudo systemctl start wsdd                           # 启动 wsdd;已 active 则跳过

关键实现细节:

  • 配置渲染不含时间戳等易变内容,保证 SHA256 比对可判定幂等(deployer.py:_render_smb_conf)
  • 备份统一走 sudo cp -a(deployer.py:_backup_file),因 /etc 下文件属主为 root,基类 auto_backup() 无权限
  • 覆盖类动作前先比对哈希,一致则跳过且不产生冗余备份

6. 验证

6.1 本机验证

systemctl is-active smbd nmbd wsdd          # 期望:三行均为 active
systemctl is-enabled smbd nmbd wsdd         # 期望:三行均为 enabled
ss -tlnp | grep -E ':445|:139'              # 期望:仅 192.168.31.249:445 与 :139,无 0.0.0.0
ss -ulnp | grep -E ':137|:138|:3702'        # 期望:nmbd 的 137/138、wsdd 的 3702(含组播)
sudo testparm -s /etc/samba/smb.conf        # 期望:返回 0,输出有效配置
sudo pdbedit -L                             # 期望:含 smbuser 条目
ls -ld /home/rain/Documents                 # 期望:drwxrwxr-x(775)
sudo -u smbuser test -w /home/rain/Documents && echo OK   # 期望:输出 OK

端到端认证与共享可见性(smbclient 已随部署安装):

# 用 authfile 传凭据,避免密码出现在命令行
printf 'username=smbuser\npassword=***\n' > /tmp/smb_auth && chmod 600 /tmp/smb_auth
smbclient -L 192.168.31.249 -A /tmp/smb_auth -m SMB3          # 期望:列出 Documents 与 IPC$
smbclient //192.168.31.249/Documents -A /tmp/smb_auth -m SMB3 -c 'ls'        # 期望:列出目录内容
smbclient //192.168.31.249/Documents -A /tmp/smb_auth -m SMB3 -c 'ls .trae'  # 期望:NT_STATUS_NO_SUCH_FILE(被 veto 阻止)
rm -f /tmp/smb_auth

注意:配置了 bind interfaces only 后 smbd 不再监听 127.0.0.1,本机自检必须使用 192.168.31.249。

6.2 Windows 侧验证

ping 192.168.31.249                                  # 期望:可通
Test-NetConnection 192.168.31.249 -Port 445          # 期望:TcpTestSucceeded : True
net use Z: \\192.168.31.249\Documents /user:smbuser ***   # 期望:命令成功完成

也可在资源管理器地址栏直接输入 \\192.168.31.249\Documents;若在「网络」中查看,应能看到主机 DELL-R620。

6.3 幂等复跑

SMB_PASSWORD='***' .venv/bin/python main.py --config config/samba_deploy.yaml
# 期望输出:状态一致,无需变更,跳过备份与执行;状态: skipped

7. 回滚

触发判据(任一达标即回滚,不临场判断):testparm 返回非 0 / 某服务非 active / smbclient 认证失败 / AppArmor 出现 smbd 拒绝记录 / 幂等复跑出现非跳过变更。

cd /home/rain/Documents/samba_ins
.venv/bin/python main.py --config config/samba_deploy.yaml --rollback   # 高危,需交互输入 YES 确认

实现体按序遍历执行:

sudo systemctl disable --now wsdd nmbd smbd         # 停止并取消自启
sudo apt-get remove -y samba wsdd smbclient         # 卸载本次安装的软件包
sudo smbpasswd -x smbuser                           # 移除 Samba 账号密码
sudo userdel smbuser                                # 删除系统账号
sudo install -d -m 0755 /etc/samba                  # 若变更前已有配置备份,则重建目录并恢复
sudo cp -a <最新备份> /etc/samba/smb.conf
sudo chmod 755 /home/rain/Documents                 # 按 logs/share_permission_before 记录恢复目录权限

备份位置:

  • /etc/samba/smb.conf.bak.<YYYYmmdd-HHmmss>
  • /etc/systemd/system/wsdd.service.bak.<YYYYmmdd-HHmmss>
  • 目录权限原值:logs/share_permission_before

回滚后验证:445/139 不再监听、id smbuser 不存在、/etc/samba/smb.conf 已还原或不存在、ls -ld /home/rain/Documents 恢复为 755。

注意:--rollback 卸包后 /etc/samba 目录可能被一并清除;若变更前该目录已存在历史配置,务必确认上表中最新备份存在,实现体会在卸载后重建目录并恢复。

8. 风险说明

风险点 说明 缓解措施
无主机防火墙 本机 ufw 未启用,445/139/137/138/3702 对整个 192.168.31.0/24 可达(含 7 台虚机) 已用 Samba 自身 hosts allow = 127.0.0.1 192.168.31.0/24 + hosts deny = 0.0.0.0/0 收敛;如需更严可启用 ufw
敏感目录外泄 共享根为整个 Documents,含 .trae、.idea 等可能存有凭据的目录 veto files + delete veto files = no 硬排除,实测访问返回 NT_STATUS_NO_SUCH_FILE
目录权限放宽 chmod g+w 使 rain 组全体获得 Documents 写权限 当前 rain 组成员仅 rain 与 smbuser;原权限 755 已记录,可一键恢复
密码强度与泄露 密码已在对话中出现,且为人工设定的较短口令 密码不落盘;建议连通后轮换为强口令,并改用 --force 重设
双 IP 混淆 本机 br0=192.168.31.249 与 eno2=192.168.31.250 同网段 已 bind interfaces only 仅绑 br0,客户端统一用 249,从 250 访问会失败(预期行为)
单点主机 本机同时承载 KVM 与 k8s,但本变更不触碰虚拟化与网络配置 变更仅新增用户态服务;未修改 netplan/网桥/路由/sysctl
wsdd unit 归属 Ubuntu 官方 wsdd 包不含 systemd unit,unit 由本工程维护 unit 内容纳入哈希比对与备份,随工程一同回滚;升级 wsdd 包不会覆盖该 unit
AppArmor 装包引入 usr.sbin.smbd profile,理论上可能拦截共享路径访问 部署流程内置拦截检查(读 30 分钟内内核日志中的 DENIED 记录),实测无拒绝
冗余备份 早期执行产生过内容相同的备份文件 现逻辑仅在内容确实变更时备份;历史冗余备份已于 2026-09-16 按哈希校验后清理完毕

来源:/home/rain/Documents/samba_ins/docs/SOP.md | 最后更新:2026-09-16 10:56(由 build/sync.py 同步,请勿在站点侧修改)