必须启用internal-sftp子系统、用户shell设为/sbin/nologin、chrootdirectory及其所有上级目录属主为root且权限严格755,并将match块置于sshd_config末尾,四者缺一不可。

要让 SFTP 用户真正被限制在指定目录内,不能靠简单改家目录或禁用 shell 就完事——必须用 OpenSSH 的 ChrootDirectory 配合 internal-sftp 子系统,且目录权限、用户 Shell、配置顺序三者缺一不可。
必须启用 internal-sftp 子系统
OpenSSH 默认可能仍使用旧版外部 sftp-server,而 chroot 功能只在内置的 internal-sftp 下生效。不改这一项,后面所有隔离规则都无效。
- 打开
/etc/ssh/sshd_config,找到类似#Subsystem sftp /usr/libexec/openssh/sftp-server的行,把它注释掉 - 添加或确认存在这一行:
Subsystem sftp internal-sftp - 改完务必执行
sudo sshd -t校验语法,再sudo systemctl restart sshd - 验证是否生效:连接后运行
ps aux | grep sftp,输出中应含internal-sftp,而非sftp-server
用户 Shell 必须设为 /sbin/nologin
SFTP 不是登录终端,用户不该拥有任何可执行的 shell。用 /bin/bash 或留空,等于给 chroot 留了后门,可能被绕过提权。
- 新建用户时直接指定:
sudo useradd -m -s /sbin/nologin sftpuser - 已有用户修改:
sudo usermod -s /sbin/nologin sftpuser - 检查结果:
getent passwd sftpuser第六字段应为/sbin/nologin - 避免使用
/bin/false,部分 OpenSSH 版本兼容性不佳,/sbin/nologin更稳妥
Chroot 目录权限必须严格满足 root:root + 755
OpenSSH 对 chroot 根目录的校验非常严格:只要属主不是 root,或组/其他有写权限(比如 775、777),连接就会被拒绝,报错 “bad ownership or modes”。
- chroot 路径(如
/sftp/sftpuser)及其所有上级路径(包括/sftp)都需执行:sudo chown root:root /sftp /sftp/sftpuser - 权限统一设为 755:
sudo chmod 755 /sftp /sftp/sftpuser - 用户真正能读写的子目录(如
/sftp/sftpuser/upload)才交给用户:sudo mkdir /sftp/sftpuser/upload && sudo chown sftpuser:sftpusers /sftp/sftpuser/upload && sudo chmod 775 /sftp/sftpuser/upload - 切勿对 chroot 根目录执行
chmod -R 777—— 这会让服务直接拒绝连接,也破坏安全前提
Match 块要放在 sshd_config 末尾且结构完整
OpenSSH 按顺序读取配置,Match 块只对它之后的指令生效。如果写在 Subsystem 上方或夹在全局配置中间,规则基本不会触发。
- 确保
Subsystem sftp internal-sftp在前,Match块在最后 - 示例配置(追加到文件末尾):
Match User sftpuser<br> ChrootDirectory /sftp/%u<br> ForceCommand internal-sftp<br> AllowTcpForwarding no<br> X11Forwarding no
- 若需批量管理,可用
Match Group sftpusers,再把用户加入该组 - 重启前必做:
sudo sshd -t;失败时查journalctl -u sshd -n 50,多数问题出在权限或路径所有权上











