我目前有一个有效的 SFTP 登录,使用私钥登录,并且用户被 chroot 到他们的主目录。
目标:保持用户 chroot 但允许对相对 chroot 目录进行写访问,而无需在任何地方指定任何路径或 cd。
换句话说,当 sftp 用户登录时,我不希望他们必须 cd 到另一个路径才能上传文件。
由于 chroot 目录需要完全 root 所有权(由于 chroot 设计),我不确定这是否可能。
在 /etc/passwd 中:
sftpuser:x:1006:1006:,,,:/home/sftpuser:/bin/false
用户登录公钥位于:
/home/sftpuser/.ssh/authorized_keys
sshd_confg 中的 Chroot 规则:
Match User sftpuser
ChrootDirectory /home/sftpuser
ForceCommand internal-sftp
AllowTCPForwarding no
X11Forwarding no
主目录权限:
# ls -l /home/ |grep sftpuser
drwxr-xr-x 5 root root 4096 May 4 11:24 sftpuser
# ls -l /home/sftpuser/
total 4
drwxrw-r-x 3 sftpuser sftpuser 4096 May 4 11:23 sftp_share
当前工作流程示例:
Connected to sftp.example.com.
sftp> ls
sftp_share
sftp> put testfile.txt
Uploading testfile.txt to /testfile.txt
remote open("/testfile.txt"): Permission denied
sftp> cd sftp_share
sftp> put testfile.txt
Uploading testfile.txt to /sftp_share/testfile.txt
testfile.txt
所需工作流程:
Connected to sftp.example.com.
sftp> put testfile.txt
Uploading testfile.txt to /testfile.txt
testfile.txt
有没有什么方法可以允许上传(放入)到默认目录,而不必先 chdir?
我确实可以灵活地移动这些目录。例如,sftp chroot 目录不必位于用户主目录中,我甚至可以更改用户主目录(但用户仍然必须能够使用 authorized_keys 登录)。
请注意:我确实了解许多 SFTP 客户端,命令行 SFTP 客户端允许在登录时定义相对路径。这超出了这个问题的范围,我希望这个配置在服务器端完成,客户端只需登录即可。
答案1
嘿@emmdee 我花了很长时间才意识到有一个简单而巧妙的技巧。你只需要让 root 成为你想要 sFTP 的父文件夹的所有者,然后使用 force 命令告诉特定用户在 CHROOT 目录中加载特定 DIR。
在你的情况下,如果你想/home/sftpuser
成为可写目录,你必须根目录的所有者/home
然后继续强制命令他/sftpuser
作为该用户或组的登陆目录。
你的/etc/ssh/sshd_conf
意愿如下:
Match User sftpuser
ChrootDirectory /home
ForceCommand internal-sftp -d /sftpuser
AllowTCPForwarding no
X11Forwarding no
完成后,您必须授予正确的权限,如前所述,root 应拥有父目录 (chroot),/home
而用户应拥有最终目录 (-d) /sftpuser
。我假设您有一个名为 sFTP 用户组sftp 用户如果不是,只需在下一个命令中省略组或将其替换为用户(根在第一和sftp 用户在第二个中)。由于我们在命令行中使用 -R 进行继承,因此您必须先从 root 所有权开始,然后再从用户所有权开始,如下所示:
sudo chown -R root:sftpusers /home
然后对于用户你可以运行:
sudo chown -R sftpuser:sftpusers /home/sftpuser
我不确定这是否有必要,但您可以随时重新启动 sshd 服务以确保所有设置都重新加载:
sudo systemctl restart sshd.service
希望这能起到奇效,我也遇到过类似的问题,而解决方案大多数时候就在我眼前。
干杯!
答案2
我知道已经过去好几年了,但是经过长时间的搜索,这篇文章帮助我找到了 98% 的答案。
为了使我能够让用户 chroot 并自动将他们带入具有写权限的自己的目录中,我使用了@African Idiot 建议的方法,并且使原始 chroot 目录归 root 用户和 FTP 组所有。
但是对我来说,将它们保存在该文件夹中并且不能...并尝试浏览其他用户的文件夹的关键是创建文件夹,chmod 710 (rwx--x---)
以便 ftp 组可以执行 internal-sftp -d /%u(即 cd 进入用户子目录)并且现在如果我尝试cd ..
进入上层目录,因为除了 root 之外没有人可以读取,所以它会失败。
drwx--x--- 6 root sftpusers uarch 6 Feb 19 15:34 ./
drwxr-xr-x 5 root root uarch 5 Feb 4 09:13 ../
drwxrwx--- 3 anotheruser anotheruser uarch 3 Feb 24 15:34 anotheruser/
drwxrwx--- 3 ftpuser ftpuser uarch 12 Feb 25 10:55 ftpuser/
希望这也能帮助其他人。
答案3
上面详述的权限“技巧”是不安全的,即在 chroot 目录上专门设置执行权限。这允许用户在猜测有效用户名的情况下更改目录并使用另一个网站的内容,尽管他们无法列出根目录中的用户目录。这也导致许多 SFTP 客户端出现问题,这些客户端要么在登录后尝试自动切换到“/”,要么 WinSCP 记住最后一个工作目录。在 WinSCP 的情况下,下次登录时会自动记住工作目录,因此用户在尝试导航到父目录后会认为他们已被锁定。
我的解决方案使用了上述概念,即 /etc/passwd 中的用户帐户引用 /var/www/www.redacted.com 网络服务器目录。这适用于 Pure-FTPD chroot jails 和 Apache,它们继续引用原始位置。但是,SSH 被配置为将 chroot 目录覆盖到 jail 位置 (/home/users/%u),其中“网站”子目录绑定到实际的网络服务器目录。
示例用户帐户:
blahweb:x:50040:33:Blah FTP Web Site User:/var/www/www.redacted.com:/sbin/nologin
^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ = static
PS:确保 /etc/shells 包含“/sbin/nologin”,组 www-data 的用户 ID 为 33。
/etc/ssh/sshd_config 中的 SFTP 配置:
Match Group www-data
X11Forwarding no
AllowTcpForwarding no
ChrootDirectory /home/users/%u
ForceCommand internal-sftp -u 0007 -d /website
然后我每小时运行以下脚本:
[root@webserver ~]# cat /etc/cron.hourly/sftp-create-chroot
#!/bin/sh
basedir='/home/users';
webdir='\/var\/www\/';
# Unmount and then cleanup all mount points (removes old sites):
grep -P " $basedir/\S+web/website " /proc/mounts | cut -d' ' -f2 | while read mountpoint; do
umount $mountpoint;
done
for dir in $basedir/*; do
[ `grep -Pc " $dir/" /proc/mounts` -eq 0 ] && find $dir -depth -type d -empty -delete;
done
# Create SFTP user directories and mount websites:
grep -P "^\S+web:x:50\d{3}:33:.*:$webdir" /etc/passwd | perl -pe "s/^([^:]+):.*:($webdir.\S+):.*/\1\t\2/g" | while read user home; do
if [ ! -d $basedir/$user ]; then
mkdir -p -m 000 $basedir/$user/website;
chmod 555 $basedir/$user;
fi
[ `grep -Pc " $basedir/$user/website " /proc/mounts` -eq 0 ] && mount --bind $home $basedir/$user/website;
done
SSH 本质上配置为在用户“blahweb”登录时将 SFTP 会话限制在 /home/users/blahweb 中。他仅对此目录本身具有读取权限,并且无法与其中的“网站”目录进行交互,除非该目录已挂载并且他的用户 ID 或组有权访问实际的网站目录。脚本在运行时会卸载所有活动挂载并清理旧用户目录,其中还包含逻辑以避免在脚本运行时标记活动挂载。
用简单的标记编写脚本,希望能够使其更易于阅读:
一切按预期工作时的目录权限:
[root@webserver ~]# dir -a /home/users/blahweb
total 4
dr-xr-xr-x 3 root root 21 Apr 27 13:17 .
drwxr-xr-x 31 root root 4096 Apr 27 13:17 ..
drwxrwx--- 2 blahweb www-data 30 Apr 27 13:05 website
当'mount --bind'失败时的目录权限:
[root@webserver ~]# dir -a /home/users/blahweb
total 4
dr-xr-xr-x 3 root root 21 Apr 27 13:17 .
drwxr-xr-x 31 root root 4096 Apr 27 13:17 ..
d--------- 2 root root 6 Apr 27 13:17 website
WinSCP 中的用户体验: