限制 SFTP 用户只能访问特定文件夹

在某些情况下, 我们希望将 SFTP 用户限制在某个特定目录内, 出于安全考虑。OpenSSH 提供了 Chroot Jail 机制来实现这一功能。

⚠️ 需要注意。在 chroot 环境下, SFTP 用户不能直接写入 /。因此要么强制他们进入一个可写的子目录, 要么提前建立合适的目录结构。

实现方式有两种:

  • 针对多个用户, 可以将他们限制在各自的 home 目录, 并把 home 目录设置到自定义路径
  • 针对单个用户, 可以在 sshd_config 中直接指定目录

本文主要介绍如何为多个用户设置

如何为多个用户进行设置

创建用户组

首先, 创建一个专门的 sftp 用户组

groupadd sftprestricted

创建目录

创建存放用户目录的路径

mkdir /location/to/your/HomeFolder

创建用户

创建新用户并将其直接加入 sftprestricted 组, 同时指定 home 目录为刚才创建的目录, 并禁用 shell 登录

useradd -d /location/to/your/HomeFolder -m USERNAME -g sftprestricted -s /sbin/nologin

说明

  • -s /bin/false/sbin/nologin 用于禁止用户直接通过 SSH 获取 shell
  • 在禁用 shell 之前不要使用 ssh-copy-id 来复制公钥, 因为 chroot 权限限制会导致 authorized_keys 无法使用

设置权限

由于 OpenSSH 对 chroot jail 有严格要求:

  • 用户 home 目录必须归 root 所有
  • 用户不能对其 home 根目录直接写入

因此, 需要调整目录权限

chown root:root /location/to/your/HomeFolder
chmod 755 /location/to/your/HomeFolder

如果要允许用户写入, 需要在其 home 目录下再创建一个子目录, 例如 /location/to/your/HomeFolder/data, 并设置权限

子目录权限可根据需要设置为 755750

mkdir /location/to/your/HomeFolder/data
chown USERNAME:sftprestricted /location/to/your/HomeFolder/data
chmod 755 /ftpusers/HomeFolder/data

这样, 用户登录后只能在 data 子目录中进行读写

启用 internal-sftp

编辑 /etc/ssh/sshd_config, 将 sftp-server 替换为 internal-sftp

# override default of no subsystems
# Subsystem     sftp    /usr/libexec/openssh/sftp-server
Subsystem       sftp    internal-sftp

UsePAM yes

这样, sftp 服务会作为 SSH 内置子系统运行, 而不会再启动独立的 sftp 进程。

从功能上看, sftp-serverinternal-sftp 基本相同, 且由同一份源码构建。

设置 Chroot Jail

编辑 /etc/ssh/sshd_config, 在末尾添加

# SFTP Chroot Jail
Match Group sftprestricted
    ChrootDirectory %h
    ForceCommand internal-sftp
    PasswordAuthentication no
    PubkeyAuthentication yes
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no

说明

  • ChrootDirectory %h: 将用户限制在其 home 目录
  • ForceCommand internal-sftp: 确保用户只能使用 SFTP, 不会执行 .bashrc 或其他命令
  • 同时禁止隧道、转发、X11 等, 强制使用公钥认证

配置密钥认证 (推荐)

最佳实践是使用 密钥认证 来进行 SSH/SFTP 连接

默认情况下, OpenSSH 会检查 /home/%u/.ssh/authorized_keys 来读取公钥

由于 home 目录权限限制, ~/.ssh/authorized_keys 在 chroot jail 中无法正常使用, 因此需要为 SFTP 用户指定一个独立的密钥存放目录, 例如 /etc/ssh/user_keys/

创建目录和密钥文件

先创建存放密钥的目录, 并为用户生成对应的 authorized_keys 文件, 并将户名附加到文件名中

mkdir /etc/ssh/user_keys
vim /etc/ssh/user_keys/authorized_keys_USERNAME

修改权限

为文件设置适当权限, 确保只有目标用户可以读取密钥

chown USERNAME:sftprestricted /etc/ssh/user_keys/authorized_keys_USERNAME
chmod 640 /etc/ssh/user_keys/authorized_keys_USERNAME

为用户组指定密钥文件位置

编辑 /etc/ssh/sshd_config, 在末尾添加以下配置, 指定自定义密钥文件路径

# SSH Key authentication for SFTP users using chroot
Match Group sftprestricted
    AuthorizedKeysFile  /etc/ssh/user_keys/authorized_keys_%u

为特定用户指定密钥文件位置

如果需要针对单个用户设置, 可以使用 Match User

Match User USERNAME
    AuthorizedKeysFile /etc/ssh/user_keys/authorized_keys_%u

允许用户写入根目录 (可选)

如果希望用户直接写入 chroot 的根目录, 可以通过 -d 强制他们进入某个子目录

# SFTP Chroot Jail
Match Group sftprestricted
    ChrootDirectory %h
    ForceCommand internal-sftp -d /subdirectory
    PasswordAuthentication no
    PubkeyAuthentication yes
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no

其中 /subdirectory 必须归用户所有, 并设置正确权限

重启 SSH 服务

配置完成后, 重启 SSH 服务并检查状态。在保持当前终端会话不关闭的情况下, 建议再开一个新终端测试 SSH 登录是否正常。

systemctl restart sshd
systemctl status sshd

调试与问题排查

首先, 仔细检查权限设置, 因为权限问题是最常见的原因。

  1. chroot 根目录必须由 root 拥有, 并且不可写
  2. 用户写入目录必须是子目录

使用详细模式调试 SFTP

sftp -vvv username@host.local

查看 SSH 日志

可以在 /etc/ssh/sshd_config 中临时开启调试日志, 调试完成后记得恢复默认配置

# Logging
# SyslogFacility AUTH
SyslogFacility AUTHPRIV
LogLevel DEBUG

修改后重启 SSH 服务并检查状态

systemctl restart sshd
systemctl status sshd

然后查看 sshd 服务日志, 确认是否有权限或其他错误。日志文件路径因系统而异, 一般在 /var/log/secure/var/log/auth.log

tail -f /var/log/secure

原文

Restrict SFTP user to a specific folder
Limit SFTP user access to specified directory

最后更新于 2025-08-28