openssh 的 sftp 可通过 internal-sftp 和 chrootdirectory 实现仅文件传输的受限访问:需配置 subsystem、forcecommand、禁用 shell 并严格设置 chroot 目录权限(root:root、755),用户工作目录在 chroot 内且可写。

OpenSSH 的 SFTP 子系统默认以内嵌方式运行(即通过 sftp-server 或 internal-sftp 作为 SSH 进程的子进程),但可通过配置使其“独立运行”——更准确地说,是让 SFTP 服务脱离交互式 Shell 登录、仅提供文件传输能力,并结合 ChrootDirectory 实现用户目录禁锢(chroot jail)。这并非启动一个完全脱离 SSH 的独立守护进程(OpenSSH 不支持纯 standalone SFTP daemon),而是通过 SSH 配置达成逻辑隔离与路径限制的效果。
启用 internal-sftp 并禁用 Shell 登录
OpenSSH 自 4.8 起内置 internal-sftp,无需额外安装 sftp-server,性能更好且更安全。需在 /etc/ssh/sshd_config 中配置:
- 确保全局启用 SFTP 子系统:
Subsystem sftp internal-sftp - 禁用该用户的交互式 Shell(防止绕过 chroot):
Match User sftpuser
ForceCommand internal-sftp
PasswordAuthentication yes
PermitTunnel no
AllowTcpForwarding no
X11Forwarding no - 关键:用户登录 shell 必须设为
/bin/false或/usr/sbin/nologin(不能是/bin/bash等可执行 shell):
sudo usermod -s /bin/false sftpuser
配置 Chroot 目录实现路径禁锢
chroot 要求目录权限严格,否则 OpenSSH 会拒绝启动 SFTP 会话(报错如 “bad ownership or modes”):
- Chroot 根目录(如
/srv/sftp/sftpuser)必须:
✓ 所有者为root
✓ 所属组为root(或配置中指定的 chroot 组)
✓ 权限为755(不可写,尤其不可被 group/o 写) - 用户实际工作目录(如
/srv/sftp/sftpuser/home)可由用户拥有并写入:
sudo mkdir -p /srv/sftp/sftpuser/home
sudo chown sftpuser:sftpuser /srv/sftp/sftpuser/home
sudo chmod 700 /srv/sftp/sftpuser/home - 在
Match块中添加:
ChrootDirectory /srv/sftp/%u
(%u表示用户名,自动展开;也可写死路径)
常见问题与验证要点
配置完成后务必重启服务并测试:
- 运行
sudo sshd -t检查配置语法是否正确 - 重启服务:
sudo systemctl restart sshd(或service ssh restart) - 客户端测试:
sftp sftpuser@localhost,成功后执行pwd应显示/,ls只能看到home目录;尝试cd /etc应失败 - 若连接立即关闭,检查日志:
sudo journalctl -u ssh -n 50 -f,常见错误包括:
• chroot 目录权限非 root:root 或含 group/o 写权限
• 用户主目录未在 chroot 内创建或权限错误
• 用户 shell 未设为/bin/false
进阶:按组统一管理多个 SFTP 用户
可将多个用户加入同一组(如 sftpusers),用 Match Group 简化配置:
-
Match Group sftpusers
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no - 创建用户时指定组:
sudo useradd -m -g sftpusers -s /bin/false sftpuser2 - 每个用户的 chroot 根目录仍需单独创建并设置权限(不能共用同一根目录)










