警告
本文最后更新于 2022-12-07,文中内容可能已过时。
文章介绍如何让sftp
也可以实现vsftpd
虚拟用户的功能。
对于运维来说,我们使用文件传输功能的时候都是优先使用vsftpd
,而不是sftp
,多数原因我想应该都是因为vsftpd
具有虚拟用户的功能,这个功能在针对特定的服务来说是非常友好的。比如php
服务降权启动时,被读取文件的文件权限问题。
上述的问题,sftp
实际上也是可以解决,借助useradd -o
选项实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
[cxd@0x5c0f ~][0]$ useradd --help
用法:useradd [选项] 登录名
useradd -D
useradd -D [选项]
选项:
-h, --help 显示此帮助信息并退出
-k, --skel SKEL_DIR 使用此目录作为骨架目录
The skeleton directory, which contains files and directories to be copied in the user\'s home directory,
when the home directory is created by useradd.
This option is only valid if the -m (or --create-home) option is specified.
If this option is not set, the skeleton directory is defined by the SKEL variable in
/etc/default/useradd or, by default, /etc/skel.
-m, --create-home 创建用户的主目录
-o, --non-unique 允许使用重复的 UID 创建用户
This option is only valid in combination with the -u option.
-s, --shell SHELL 新账户的登录 shell
-u, --uid UID 新账户的用户 ID
|
以下定义WEBServer
的基础用户为www
,以php
为例,php-fpm
启动进程所属则为www
用户,那么也只能读取www
用户所拥有操作权限的文件。
创建sftp
登陆用户,使用-o
选项,让当前用户保持与www
同属主UID
、同属组GID
1
2
3
|
$> groupadd -o -g $(id -g www) webapp
$> useradd -o -u $(id -u www) -g webapp -m -k $(mktemp -d) -s /bin/false webapp
# 此帐号只是sftp使用,所有创建时候添加-k选项,不让useradd复制/etc/skel下内容
|
帐号创建成功后,可在/etc/passwd
中看到该帐号,此时应可以看到他的所属主和属组和www
帐号一致
1
2
3
4
5
6
7
8
|
# 由于ssh-keygen在创建默认密钥时无法更新此路径,因此需要主动创建该目录
$> mkdir /home/webapp/.ssh
# 此处授权可以直接授权www:www,为了看起来更清晰,此处授权还是用创建时的用户,但无论使用的是那一个,系统显示都会是www
$> chown webapp:webapp /home/webapp/.ssh
# 密钥创建
$> su - webapp -s /bin/bash -c "ssh-keygen -f ~/.ssh/id_rsa -t rsa -b 4096 -N ''"
$> su - webapp -s /bin/bash -c "cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# 注意此项, 网上的sftp搭建教程基本都是说需要将此项切换为, Subsystem sftp internal-sftp
# 切换后将绕过"管理员可能依赖登录shell配置来阻止某些用户登录"。但我们上述使用的是重复UID,所以此处不能更改
# 若更改,则会导致共用UID的用户之间可相互登陆。
# 差异参见: https://serverfault.com/questions/660160/openssh-difference-between-internal-sftp-and-sftp-server
# 差异参见: http://129.226.226.195/post/21921.html
Subsystem sftp /usr/libexec/openssh/sftp-server
# 指定匹配用户
Match User webapp
# 用chroot将用户的根目录指向到固定位置
ChrootDirectory /sftpdir
# -l 指定日志收集 -f 收集内容(应该是) internal-sftp 请参看上述连接自行参悟
ForceCommand internal-sftp -l INFO -f AUTH
# 以下其他配置自行参悟
PermitTTY no
X11Forwarding no
AllowTcpForwarding no
PasswordAuthentication no
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# 上述操作完成后,还需要创建一个chroot目录
$> mkdir /sftpdir
$> echo hello > /sftpdir/readme.md
# 注意目录属主必须为root,属组可以不是,权限不能超过755
$> chown root.root /sftpdir
$> chmod 755 /sftpdir
# 重启sshd服务(重载也可以)
$> systemctl reload sshd
## 登陆测试
$> sftp -i /home/webapp/.ssh/id_rsa webapp@127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:hQkISJWcE+gHf1WAT2bIWSwiAJRD81Bv3wZd+1vZOuU.
ECDSA key fingerprint is MD5:0e:e5:1a:c7:6c:97:fb:48:95:d2:c9:86:bb:d0:7d:91.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
Connected to 127.0.0.1.
sftp> ls -l
-rw-r--r-- 1 0 0 6 Dec 8 06:31 readme.md
sftp> pwd
Remote working directory: /
sftp>
|
至此,sftp
搭建完成, 当然由于 /
目录属主为root
,sftp
目前只能登陆,无法上传,需要在/sftpdir
目录下创建目录,然后授权www
用户即可,在该目录下进行增、删、改操作。