SFTP chroot
OpenSSH 4.9+ 包含了内置的 SFTP chroot 功能,但需要对常规安装进行一些调整。
安装
安装并配置 OpenSSH。运行后,请确保 sftp-server 已正确设置
/etc/ssh/sshd_config
Subsystem sftp /usr/lib/ssh/sftp-server
使用 sftp 或 SSHFS 访问文件。许多标准的 FTP 客户端也应该可以工作。
配置
设置文件系统
- 阅读者可以自行选择文件访问方案。例如,可以选择性地为接收(可写)空间和/或只读空间创建子目录。这不需要直接在
/srv/ssh/jail下完成 —— 也可以在实际分区上完成,然后通过绑定挂载(bind mount)挂载进去。 - 也可以直接 chroot 到
/home目录,从而跳过绑定挂载,但目标用户主目录必须由 root 所有
# chown root:root /home/<username> # chmod 0755 /home/<username>
将要共享的实际 文件系统绑定挂载到该目录。在本例中,使用 /mnt/data/share,由 用户 root 所有,且八进制 权限为 755
# chown root:root /mnt/data/share # chmod 755 /mnt/data/share # mkdir -p /srv/ssh/jail # mount -o bind /mnt/data/share /srv/ssh/jail
在 fstab 中添加条目,使绑定挂载在重启后依然有效
/etc/fstab
/mnt/data/share /srv/ssh/jail none bind 0 0
创建非特权用户
Match User 代替 Match Group。创建 sftponly 用户组
# groupadd sftponly
创建一个属于 sftponly 组且被拒绝 shell 登录访问的 用户
# useradd -G sftponly -s /usr/bin/nologin -d /srv/ssh/jail username
-s /usr/bin/nologin)。设置一个(复杂的)密码以防止出现 account is locked 错误(即使使用密钥验证也可能会出现)
# passwd username
配置 OpenSSH
Match User 而非 Match Group。/etc/ssh/sshd_config
Subsystem sftp /usr/lib/ssh/sftp-server Match Group sftponly ChrootDirectory %h ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no PasswordAuthentication no
重启 sshd.service 以确认更改。
修复 authorized_keys 的路径
(pre)auth 错误,请在客户端和服务器端使用 OpenSSH 的 调试模式。使用 AuthorizedKeysFile 的标准路径时,chroot 用户的 SSH 密钥验证将失败。为了修复此问题,请在 /etc/ssh/sshd_config 的 AuthorizedKeysFile 中追加一个 root 所有的目录,例如 /etc/ssh/authorized_keys
/etc/ssh/sshd_config
AuthorizedKeysFile /etc/ssh/authorized_keys/%u .ssh/authorized_keys PermitRootLogin no PasswordAuthentication no PermitEmptyPasswords no Subsystem sftp /usr/lib/ssh/sftp-server
创建 authorized_keys 文件夹,在客户端生成 SSH 密钥,将密钥内容复制到服务器的 /etc/ssh/authorized_keys 中(或使用任何其他首选方法),并设置正确的权限
# mkdir /etc/ssh/authorized_keys # chown root:root /etc/ssh/authorized_keys # chmod 755 /etc/ssh/authorized_keys # echo 'ssh-rsa <key> <username@host>' >> /etc/ssh/authorized_keys/username # chmod 644 /etc/ssh/authorized_keys/username
重启 sshd.service。
技巧与提示
写入权限
绑定路径必须完全由 root 所有,但文件和/或子目录不需要。在以下示例中,用户 www-demo 使用 /srv/ssh/www/demo 作为监狱目录
# mkdir /srv/ssh/www/demo/public_html # chown www-demo:sftponly /srv/ssh/www/demo/public_html # chmod 755 /srv/ssh/www/demo/public_html
用户现在应该能够在该目录内创建文件/子目录。有关更多信息,请参阅 文件权限和属性。
仅允许上传
若要仅允许通过 sftp 上传文件并禁止下载文件,请修改 ForceCommand internal-sftp 行
/etc/ssh/sshd_config
Match Group sftponly ForceCommand internal-sftp -u 0666 -p realpath,open,write,close,lstat
日志记录
用户将无法访问 /dev/log。当用户连接并尝试下载文件时,可以通过对该进程运行 strace 来观察到这一点。
创建子目录
在 ChrootDirectory 中创建子目录 dev,例如
# mkdir /usr/local/chroot/user/dev # chmod 755 /usr/local/chroot/user/dev
现在你应该在 /usr/local/chroot/user/dev/log 创建一个将被 openssh 使用的套接字。你可以直接将此套接字绑定到 /dev/log(如果你使用 journald,则绑定到 /run/systemd/journal/dev-log),或者使用 syslog-ng/rsyslog 创建。
绑定到 journald
# touch /usr/local/chroot/user/dev/log # mount --bind /run/systemd/journal/dev-log /usr/local/chroot/user/dev/log
为了使其永久生效,请在 fstab 中添加条目
/etc/fstab
/run/systemd/journal/dev-log /usr/local/chroot/user/dev/log none bind,nofail,x-systemd.requires=sshd.service
Syslog-ng 配置
在 /etc/syslog-ng/syslog-ng.conf 中为日志添加一个新源并添加配置,例如修改以下部分
source src {
unix-dgram("/dev/log");
internal();
file("/proc/kmsg");
};
更改为
source src {
unix-dgram("/dev/log");
internal();
file("/proc/kmsg");
unix-dgram("/usr/local/chroot/theuser/dev/log");
};
并追加
#sftp configuration
destination sftp { file("/var/log/sftp.log"); };
filter f_sftp { program("internal-sftp"); };
log { source(src); filter(f_sftp); destination(sftp); };
(可选)如果你想同样将 SSH 消息记录到独立的文件中
#sshd configuration
destination ssh { file("/var/log/ssh.log"); };
filter f_ssh { program("sshd"); };
log { source(src); filter(f_ssh); destination(ssh); };
(来自 Syslog-ng#Move log to another file)
OpenSSH 配置
编辑 /etc/ssh/sshd_config,将所有 internal-sftp 替换为 internal-sftp -f AUTH -l VERBOSE。
重启服务
重启 syslog-ng 和 sshd 服务。
/usr/local/chroot/theuser/dev/log 现在应该已经存在。
SFTP 的替代方案
安全复制协议 (SCP)
安装 openssh 会提供用于传输文件的 scp 命令。SCP 可能比使用 SFTP 更快 [1]。
安装 rsshAUR 或 scponly 作为替代的 shell 解决方案。
Scponly
对于现有用户,只需将用户的 shell 设置为 scponly
# usermod -s /usr/bin/scponly username
更多详情请参阅 Scponly Wiki。
添加 chroot 监狱
该软件包附带一个创建 chroot 的脚本。要使用它,请运行
# /usr/share/doc/scponly/setup_chroot.sh
- 提供答案。
- 检查
/path/to/chroot的所有者为root:root且对其他用户具有r-x权限。 - 将选定用户的 shell 更改为
/usr/bin/scponlyc。 - sftp-server 可能需要一些 libnss 模块,例如 libnss_files。将它们复制到 chroot 的
/lib路径。