企业 SFTP 服务一键部署:基于 OpenSSH 实现部门隔离与国产化适配
在国产操作系统替代浪潮中,如何快速搭建安全、可控的文件共享服务?本文分享一套自动化部署方案,实现"开箱即用"的 SFTP 服务。
一、业务背景:国产化替代下的文件共享难题
随着信创产业加速落地,越来越多的政府、金融、能源企业将原有 CentOS 迁移至国产 Linux 发行版,如 Anolis OS、openEuler、Rocky Linux、AlmaLinux 等。在这些环境中,常见的商业文件共享软件(如 Serv-U、WS_FTP)要么授权昂贵,要么对国产系统支持不佳。而传统的 FTP 协议明文传输、防火墙配置复杂,已逐渐被企业安全策略淘汰。
SFTP(SSH File Transfer Protocol) 凭借其基于 SSH 的加密通道、简单开放端口(22)、天然支持 Linux 权限模型等优势,成为内部文件共享的首选方案。然而,手工配置 SFTP 的 Chroot 隔离、多部门用户管理、SELinux 策略等步骤繁琐且易错,急需一套自动化工具。
二、需求分析与痛点识别
在与多家企业运维团队沟通后,我们归纳出以下核心需求与痛点:
| 需求点 | 具体描述 | 手工配置痛点 |
|---|---|---|
| 部门隔离 | 不同部门(行政、市场、设计、研发)的文件互相不可见 | 需逐一配置 ChrootDirectory,修改 Match Group 块 |
| 用户权限精细 | 同一部门内用户可共享可写目录,且用户仅能 SFTP 不能 SSH | 需设置 shell 为 /sbin/nologin,配置家目录与属主 |
| 快速批量创建 | 一次性创建数十个用户并分配密码 | 手工 useradd + chpasswd 效率极低,密码管理混乱 |
| 国产系统兼容 | 在 Anolis OS、openEuler 等系统上无报错运行 | 不同发行版的 SELinux 布尔值名称、服务管理存在差异 |
| 可重复执行 | 部署脚本应幂等,支持后续增加用户或重置 | 缺乏标准化,二次维护成本高 |
基于以上痛点,我们设计了一套 一键式 SFTP 部署脚本,并已在阜阳云动科技内部及多家客户环境验证。
三、方案设计:打造"一键式"SFTP 服务端部署脚本
3.1 技术选型
- 底层服务 :OpenSSH 自带的
internal-sftp(无需额外安装 vsftpd 或 proftpd) - 隔离机制 :Chroot 目录 + 专用系统组(
sftp-*) - 自动化工具:Bash 脚本,兼容 systemd、firewalld、SELinux
- 密码策略 :初始明文密码在脚本中定义,首次登录强制修改(生产环境建议结合
chage)
3.2 目录结构设计
/srv/sftp/ # SFTP 根目录(所有部门)
├── admin/ # 行政部
│ └── files/ # 可写子目录(用户实际家目录)
├── market/ # 市场部
│ └── files/
├── design/ # 设计部
│ └── files/
└── develop/ # 研发部
└── files/
- Chroot 原理 :用户登录后,
/被映射为/srv/sftp/部门名,因此用户只能看到/files目录。 - 权限设计 :
- 部门根目录(如
/srv/sftp/admin)属主root:root,权限755→ 用户无法在此创建文件。 - 可写子目录
/files属主root:sftp-admin,权限775→ 用户可读写,同组用户可共享。
- 部门根目录(如
3.3 用户与组映射
脚本内置了 4 个部门、10 个虚拟用户(可根据实际修改):
- 行政部:admin01, admin02
- 市场部:market01, market02, market03
- 设计部:design01, design02
- 研发部:develop01, develop02, develop03
每个用户属于对应部门组,家目录指向 /部门根目录/files,Shell 禁用。
3.4 核心安全加固
- 禁止 root 登录(
PermitRootLogin no) - 仅允许密码认证(可后续开启密钥)
- 禁用 TCP 转发、X11 转发
- 配置 SELinux 布尔值:
ssh_sysadm_login、sftp_enable_homedirs、sshd_enable_password_auth
四、脚本核心代码节选(完整版见文末)
由于篇幅限制,以下展示脚本中最关键的几个函数:
4.1 部门目录与组创建
bash
create_dept_structure() {
DEPTS=("admin" "market" "design" "develop")
for dept in "${DEPTS[@]}"; do
groupadd "sftp-$dept" || true
DEPT_ROOT="$SFTP_ROOT/$dept"
mkdir -p "$DEPT_ROOT"
chown root:root "$DEPT_ROOT"
chmod 755 "$DEPT_ROOT"
FILES_DIR="$DEPT_ROOT/files"
mkdir -p "$FILES_DIR"
chown "root:sftp-$dept" "$FILES_DIR"
chmod 775 "$FILES_DIR"
done
}
4.2 批量用户创建
bash
declare -A USERS=(
["admin01"]="admin01@pwd"
["market01"]="market01@pwd"
# ...
)
declare -A DEPARTMENTS=(
["admin01"]="admin"
["market01"]="market"
# ...
)
create_sftp_users() {
for user in "${!USERS[@]}"; do
dept="${DEPARTMENTS[$user]}"
group="sftp-$dept"
useradd -g "$group" -d "$SFTP_ROOT/$dept/files" -s /sbin/nologin -M "$user"
echo "$user:${USERS[$user]}" | chpasswd
done
}
4.3 sshd_config 动态配置
bash
cat >> /etc/ssh/sshd_config << EOF
Subsystem sftp internal-sftp
Match Group sftp-admin
ChrootDirectory /srv/sftp/admin
ForceCommand internal-sftp -d /files
AllowTcpForwarding no
X11Forwarding no
# ... 其他部门类似
EOF
4.4 SELinux 策略适配
bash
if [ "$(getenforce)" = "Enforcing" ]; then
setsebool -P ssh_sysadm_login on
setsebool -P sftp_enable_homedirs on
setsebool -P sshd_enable_password_auth on
fi
五、部署效果演示(成功输出摘要)
在一台 Anolis OS 8.9 服务器上执行脚本后,输出摘要如下:
[root@MiWiFi-RA70-srv ~]# ./install-sftp.sh
╔══════════════════════════════════════════════════════════════╗
║ 企业级 SFTP 一键部署脚本 (Chroot 隔离版) ║
║ 基于 OpenSSH - 支持 RHEL 8/9 及衍生版 ║
╚══════════════════════════════════════════════════════════════╝
[STEP 0] 检查系统权限...
2026-04-16 03:26:10 - 系统权限检查通过
└─ [✓] root 权限验证成功
[STEP 1] 检测系统类型和版本...
2026-04-16 03:26:10 - 检测到系统: Anolis OS 8.10 (rpm_based)
└─ [✓] 检测到系统: Anolis OS 8.10
└─ [✓] 包管理器: dnf
[STEP 2] 安装 OpenSSH 服务器...
└─ [✓] OpenSSH 服务已就绪
2026-04-16 03:26:13 - OpenSSH 服务安装/检查完成
[STEP 3] 创建部门组和目录结构...
2026-04-16 03:26:13 - 创建组 sftp-admin
2026-04-16 03:26:13 - 部门目录创建: /srv/sftp/admin
2026-04-16 03:26:13 - 创建组 sftp-market
2026-04-16 03:26:13 - 部门目录创建: /srv/sftp/market
2026-04-16 03:26:13 - 创建组 sftp-design
2026-04-16 03:26:13 - 部门目录创建: /srv/sftp/design
2026-04-16 03:26:13 - 创建组 sftp-develop
2026-04-16 03:26:13 - 部门目录创建: /srv/sftp/develop
└─ [✓] 部门组和目录结构创建完成
[STEP 4] 创建 SFTP 用户并设置密码...
2026-04-16 03:26:13 - 创建用户 admin01 (部门: admin)
2026-04-16 03:26:13 - 设置密码 for admin01
2026-04-16 03:26:14 - 创建用户 admin02 (部门: admin)
2026-04-16 03:26:14 - 设置密码 for admin02
2026-04-16 03:26:14 - 创建用户 market01 (部门: market)
2026-04-16 03:26:14 - 设置密码 for market01
2026-04-16 03:26:14 - 创建用户 market02 (部门: market)
2026-04-16 03:26:14 - 设置密码 for market02
2026-04-16 03:26:14 - 创建用户 market03 (部门: market)
2026-04-16 03:26:14 - 设置密码 for market03
2026-04-16 03:26:14 - 创建用户 develop03 (部门: develop)
2026-04-16 03:26:14 - 设置密码 for develop03
2026-04-16 03:26:14 - 创建用户 develop02 (部门: develop)
2026-04-16 03:26:14 - 设置密码 for develop02
2026-04-16 03:26:14 - 创建用户 develop01 (部门: develop)
2026-04-16 03:26:15 - 设置密码 for develop01
2026-04-16 03:26:15 - 创建用户 design02 (部门: design)
2026-04-16 03:26:15 - 设置密码 for design02
2026-04-16 03:26:15 - 创建用户 design01 (部门: design)
2026-04-16 03:26:15 - 设置密码 for design01
└─ [✓] SFTP 用户创建完成
[STEP 5] 备份原始 SSH 配置文件...
└─ [✓] 已备份至 /etc/ssh/sshd_config.bak_20260416
2026-04-16 03:26:15 - SSH 配置文件备份完成
[STEP 6] 配置 SSH 守护进程 (SFTP + Chroot)...
└─ [✓] sshd_config 语法正确
2026-04-16 03:26:15 - sshd_config 配置完成
[STEP 7] 配置防火墙规则...
└─ [WARN] firewalld 未运行,请手动确保端口 22 开放
2026-04-16 03:26:15 - 防火墙配置完成
[STEP 8] 配置 SELinux 策略...
└─ [INFO] SELinux 未处于强制模式,跳过
2026-04-16 03:26:15 - SELinux 配置完成
[STEP 9] 重启 SSH 服务...
└─ [✓] SSH 服务重启成功
2026-04-16 03:26:17 - SSH 服务重启完成
[STEP 10] 验证 SFTP 服务配置...
├─ [✓] SSH 服务状态: active
├─ [✓] 端口 22 监听: 是
└─ [✓] SFTP 子系统可用(internal-sftp)
2026-04-16 03:26:17 - SFTP 服务验证完成
╔══════════════════════════════════════════════════════════════╗
║ SFTP 服务部署完成信息 ║
╚══════════════════════════════════════════════════════════════╝
● 系统版本: Anolis OS 8.10
● SFTP 服务: OpenSSH option
● 根目录: /srv/sftp
┌────────────────────────────────────────────────────────────┐
│ 用户账号信息 │
├────────────────────────────────────────────────────────────┤
用户名 密码 登录后路径
─────────────────────────────────────────────────────────────────
admin01 admin01@pwd /files (在部门根目录下)
admin02 admin02@pwd /files (在部门根目录下)
design01 design01@pwd /files (在部门根目录下)
design02 design02@pwd /files (在部门根目录下)
develop01 develop01@pwd /files (在部门根目录下)
develop02 develop02@pwd /files (在部门根目录下)
develop03 develop03@pwd /files (在部门根目录下)
market01 market01@pwd /files (在部门根目录下)
market02 market02@pwd /files (在部门根目录下)
market03 market03@pwd /files (在部门根目录下)
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ 网络访问信息 │
├────────────────────────────────────────────────────────────┤
│ SFTP 地址: sftp://192.168.31.33:22 │
│ 客户端: FileZilla, WinSCP, 命令行 sftp user@IP │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ 服务管理 │
├────────────────────────────────────────────────────────────┤
│ systemctl start|stop|restart|status sshd │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ 目录结构 │
├────────────────────────────────────────────────────────────┤
│ /srv/sftp/admin/files - 行政部可写区域 │
│ /srv/sftp/market/files - 市场部可写区域 │
│ /srv/sftp/design/files - 设计部可写区域 │
│ /srv/sftp/develop/files - 研发部可写区域 │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ 安全提醒 │
├────────────────────────────────────────────────────────────┤
│ 1. 所有用户已禁用 shell,仅允许 SFTP 登录 │
│ 2. 用户被 chroot 到部门根目录,无法访问系统文件 │
│ 3. 定期修改用户密码:passwd <用户名> │
│ 4. 查看登录日志:journalctl -u sshd -f │
└────────────────────────────────────────────────────────────┘
✅ 企业级 SFTP 服务部署完成!
安装日志: /var/log/sftp_deploy_20260416_032610.log



验证测试 :使用 sftp market01@服务器IP 登录,执行 pwd 显示 /files,尝试 ls / 只能看到 files 目录,无法访问系统文件,隔离生效。
六、后期维护建议(由阜阳云动科技提供)
脚本部署完成后,日常运维仍需关注以下几点:
6.1 用户增删改
- 新增用户 :手动编辑脚本中的
USERS和DEPARTMENTS数组,重新执行脚本(已有用户会跳过,新用户被创建)。 - 删除用户 :
userdel -r 用户名,同时清理USERS数组避免误重建。 - 重置密码 :
passwd 用户名或echo "新密码" | chpasswd。
6.2 磁盘空间与日志
- 定期清理
/srv/sftp/*/files中的过期文件,可配合tmpwatch或cron任务。 - SFTP 传输日志:
journalctl -u sshd -f | grep "sftp"。 - 审计用户登录:
last | grep sftp。
6.3 安全加固进阶
- 禁用密码,改用密钥认证 :修改
/etc/ssh/sshd_config中PasswordAuthentication no,并为每个用户配置AuthorizedKeysFile。 - 限制用户传输速率 :在
Match Group块中添加SftpRateLimit(需 OpenSSH 9.0+,或使用tc限流)。 - IP 白名单 :通过
sshd_config的AllowUsers或Match Address实现。
6.4 备份与恢复
- 备份目录:
tar czf sftp_backup.tar.gz /srv/sftp /etc/ssh/sshd_config - 恢复时先解压目录,再重启
sshd,注意检查 SELinux 上下文:restorecon -Rv /srv/sftp
6.5 跨部门文件共享
当前设计部门之间天然隔离。若需跨部门读写(如设计部向市场部交付素材),可考虑:
- 创建公共组
sftp-share,在某个部门下建立子目录,属组改为sftp-share。 - 或使用软链接(注意 Chroot 环境内软链接不能指向外部,需使用
mount --bind)。
脚本完整版获取 :关注账号,回复 SFTP一键部署 即可下载。
技术支持:如遇国产系统兼容性问题(统信 UOS、麒麟等),欢迎联系我们获取适配版本。
阜阳云动科技有限公司,专注于系统运维、服务器网络、安全及 AI 大模型落地。我们坚信:好的运维工具,应该让复杂变简单。