能,但必须同时满足chrootdirectory路径所有权为root、权限≤755、启用internal-sftp子系统、用户shell设为/sbin/nologin或/bin/false这四个硬性条件,缺一不可;否则连接失败,报错write failed: broken pipe或connection closed。

直接给结论:必须用 ChrootDirectory 配合严格权限控制,否则所谓“限制目录”形同虚设——用户仍可能逃逸或通过 SSH 登录绕过。
为什么 ChrootDirectory 的父目录必须是 root 所有且权限 ≤755
OpenSSH 的 internal-sftp 在启动 chroot 时会逐级检查从 / 到目标目录的每一级路径。只要其中任意一级不是 root:root(或至少属主是 root),服务就会拒绝启动,并在 journalctl -u sshd 中报错:fatal: bad ownership or modes for chroot directory component。
常见错误操作包括:
- 把
/home/sftpuser直接设为ChrootDirectory,但该目录属主是sftpuser—— 必须chown root:root /home/sftpuser - 设成
/home/sftpuser/files,但/home/sftpuser权限是 775 或含 sticky bit —— 必须chmod 755 /home/sftpuser - 忘记
/home或/本身被意外改过属主 —— 虽然极少见,但ls -ld / /home应确认属主为 root
ForceCommand internal-sftp 为什么不能替代禁用 shell
即使写了 ForceCommand internal-sftp,如果用户 shell 是 /bin/bash 或 /bin/sh,仍可通过普通 SSH 连接执行命令,完全绕过 SFTP 限制。
正确做法是:
- 创建用户时指定无登录 shell:
useradd -s /sbin/nologin sftpuser(CentOS/RHEL)或useradd -s /usr/sbin/nologin sftpuser(Debian/Ubuntu) - 已有用户需用
usermod -s /sbin/nologin sftpuser修改 - 绝对不要用
/bin/false或/bin/true—— 某些旧版 OpenSSH 会因此拒绝 sftp 登录
如何让用户在 chroot 内可写子目录,但根目录只读
chroot 根目录(如 /home/sftpuser)必须由 root 拥有、不可写;但用户需要上传文件,就得在它下面建一个可写子目录,并把属主设为该用户。
例如:
mkdir -p /home/sftpuser/upload chown sftpuser:sftpuser /home/sftpuser/upload chmod 755 /home/sftpuser/upload
注意:chmod 700 不行——因为 chroot 根目录的 group 和 other 权限必须至少是 r-x,否则 sftp 进程无法进入该子目录。
更安全的做法是用独立组隔离:
- 创建组:
groupadd sftpwriters - 把用户加进组:
usermod -aG sftpwriters sftpuser - 设子目录属组为该组:
chown root:sftpwriters /home/sftpuser/upload && chmod 775 /home/sftpuser/upload
最易被忽略的一点:每次改完 /etc/ssh/sshd_config,必须先运行 sshd -t 测试语法,再 systemctl restart sshd。跳过 sshd -t 导致服务崩溃,是运维现场最高频的误操作。











