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

直接说结论:能,但必须同时满足 ChrootDirectory 路径所有权、权限、internal-sftp 子系统启用、用户 Shell 为 /sbin/nologin(或 /bin/false)这四个硬性条件,缺一不可;否则连接会直接失败,报错通常是 Write failed: Broken pipe 或 Connection closed。
ChrootDirectory 路径为什么必须是 root:root 且权限 ≤755
OpenSSH 的 sshd 进程以 root 身份启动 chroot,它要求整个路径链(从根目录到 ChrootDirectory 指定路径)的每个父目录都由 root 拥有,且不能被组或其他用户写入。否则 SSH 会拒绝加载该配置,日志里会出现 bad ownership or modes for chroot directory。
-
/sftp/sftpuser必须sudo chown root:root /sftp/sftpuser -
/sftp也必须是root:root,且chmod 755 /sftp(不能是 775 或 777) - 如果误设
chmod 775 /sftp/sftpuser,SFTP 登录会静默失败,无明确提示
为什么必须用 internal-sftp 而不是 sftp-server
internal-sftp 是 OpenSSH 内建的 SFTP 子系统,支持 ChrootDirectory;而传统外置的 /usr/libexec/openssh/sftp-server 不支持 chroot,强行配置会导致用户登录后立即断开,sshd -T 检查时也会报 Bad configuration option: ChrootDirectory(当 Subsystem 没切对时)。
- 确认当前配置:检查
/etc/ssh/sshd_config中是否注释掉旧行:#Subsystem sftp /usr/libexec/openssh/sftp-server - 启用新子系统:
Subsystem sftp internal-sftp(必须在Match块之前) -
Match Group sftpusers块内必须含ForceCommand internal-sftp,否则用户仍可能绕过限制获得 shell
用户家目录结构怎么组织才真正可写
chroot 后,用户看到的 / 就是 ChrootDirectory 路径,但该路径本身不能由用户写入(否则违反安全前提)。所以必须在其下创建一个子目录供上传,并把所有权移交用户。
- 执行:
sudo mkdir /sftp/sftpuser/upload - 移交:
sudo chown sftpuser:sftpusers /sftp/sftpuser/upload - 权限设为
755或775均可(只要用户属于sftpusers组) - 用户登录后,在 SFTP 客户端里看到的根目录是空的,
cd upload才能上传文件
常见连接失败的三个典型现象和对应检查点
实际部署中最容易卡在这三处,建议按顺序排查:
- 报错
Connection closed→ 检查ChrootDirectory及其所有上级目录是否全是root:root且chmod 755 - 报错
Write failed: Broken pipe→ 检查sshd_config是否启用了internal-sftp,且Match块中没漏掉ForceCommand internal-sftp - 用户能登录但看不到任何目录 → 检查用户 Shell 是否仍是
/bin/bash,必须是/sbin/nologin;否则 SSH 会尝试启动 shell 而非 SFTP 子系统
chroot 隔离本质是路径重映射,不涉及进程虚拟化,所以它轻量但边界清晰——一旦路径所有权或子系统配置出错,就完全不可用,没有“差不多能用”的中间状态。











