利用nginx+sftp实现一个可供用户下载的服务
公司服务端开发小伙伴来提需求啦,好像还很紧急的样子。宁静的日子也就这样被打破。据他描述,需求大概是:做一个可以咱们自己自由上传,而用户那边通过一个链接就可以下载 app 的服务。
经过讨论:想实现这个,一共有两部分,首先是本地将文件上传,其次是普通用户下载。
上传就用 sftp 了。
从技术角度来分析,几个要求:
- 1、从安全方面看,sftp 会更安全一点。
- 2、线上服务器提供在线服务,对用户需要控制,只能让用户在自己的 home 目录下活动。
- 3、用户只能使用 sftp,不能 ssh 到机器进行操作。
提供 sftp 服务,可以用系统自带的 internal-sftp,也可以使用 vsftpd,这里需求不多,直接选用internal-sftp
。
限制用户
只能在自己的 home 目录下活动,这里需要使用到chroot
,openssh 4.8p1 以后都支持 chroot,我现在用的是 CentOS 6.3,自带的 openssh 已经是 5.3p1,足够了。
ssh -V
#查看openssh的版本,如果低于4.8p1,需要自行升级安装,不在这里具体介绍了。
2
3
假设,有一个名为test
的组,这个组中的用户只能使用sftp
,不能使用ssh
,且 sftp 登录后只能在自己的 home 目录下活动。
# 1、创建 sftp 组
groupadd test
# 2、创建一个 sftp 用户,名为 erya
。
(原来的教程是创建了一个系统用户,不能登陆,现在可以创建一个普通用户,然后通过秘钥进行登陆)
useradd -g test erya
passwd erya
2
# 3、创建目录并分配权限。
test 组的用户的 home 目录统一指定到 / data/sftp 下,按用户名区分,这里先新建一个 erya 目录,然后指定 erya 的 home 为 / data/sftp/erya
mkdir -p /data/sftp/erya
usermod -d /data/sftp/erya erya
2
# 4、配置 sshd_config。
编辑 ssh 配置文件 / etc/ssh/sshd_config。
# 1,注释如下行。
vim /etc/ssh/sshd_config
Subsystem sftp /usr/libexec/openssh/sftp-server
#注释此行
2
3
4
# 2,添加如下几行。
Subsystem sftp internal-sftp
#这行指定使用sftp服务使用系统自带的internal-sftp
Match Group sftp
#这行用来匹配sftp组的用户,如果要匹配多个组,多个组之间用逗号分割
当然,也可以匹配用户
Match User mysftp
#这样就可以匹配用户了,多个用户名之间也是用逗号分割,但我们这里按组匹配更灵活和方便
ChrootDirectory /data/sftp/%u
#用chroot将用户的根目录指定到/data/sftp/%u,%u代表用户名,这样用户就只能在/data/sftp/%u下活动,chroot的含义,可以参考这里:http://www.ibm.com/developerworks/cn/linux/l-cn-chroot/
ForceCommand internal-sftp
#指定sftp命令
AllowTcpForwarding no
X11Forwarding no
#这两行,如果不希望该用户能使用端口转发的话就加上,否则删掉
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
注意:里边的注释是为了帮助理解,实际使用中可以去掉。
# 5、设定 Chroot 目录权限。
chown root:test /data/sftp/erya
chmod 755 /data/sftp/erya
2
错误的目录权限设定会导致在 log 中出现”fatal: bad ownership or modes for chroot directory XXXXXX
” 的内容.
# 1,目录的权限设定有两个要点
- 1、由 ChrootDirectory 指定的目录开始一直往上到系统根目录为止的目录拥有者都只能是 root
- 2、由 ChrootDirectory 指定的目录开始一直往上到系统根目录为止都不可以具有群组写入权限
# 2,所以遵循以上两个原则
- 1)我们将 / data/sftp/erya 的所有者设置为了 root,所有组设置为 test
- 2)我们将 / data/sftp/erya 的权限设置为 755,所有者 root 有写入权限,而所有组 test 无写入权限
# 6、建立 erya 用户登入后可写入的目录。
照上面设置后,在重启 sshd 服务后,用户 erya 已经可以登录,但使用 chroot 指定根目录后,根应该是无法写入的,所以要新建一个目录供 erya 上传文件。这个目录所有者为 erya,所有组为 test,所有者有写入权限,而所有组无写入权限。
mkdir /data/sftp/erya/upload
chown erya:test /data/sftp/erya/upload
chmod 755 /data/sftp/erya/upload
2
3
# 7、重启 sshd 服务。
service sshd restart
到这里,我们就可以通过 sftp 客户端登录并可以上传文件到upload
目录。
如果还是不能在此目录下上传文件,提示没有权限,检查 SElinux 是否关闭,可以使用# setenforce 0
指令关闭临时 SElinux。
或者修改/etc/selinux/config
文件中的SELINUX="" 为 disabled
,然后重启,进行永久关闭。
此时可以通过 Linux 命令行登陆刚才配置的 sftp 服务了。
常规登陆:sftp erya@192.168.96.219 指定端口:sftp erya@192.168.96.219 -oPort=2222
也可以用过 file-zilla,sftp 等客户端登陆,进行上传下载。
然后是对下载端进行配置。
# 8,安装 nginx 服务。
进入到配置文件中,配置如下内容:
server {
listen 80;
server_name sftp.erya.net;
charset utf-8;
location / {
root /data/sftp/erya/upload;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
}
2
3
4
5
6
7
8
9
10
11
nginx -t
检测一下配置文件。
nginx -s reload
重新加载。
然后对刚才配置的域名进行解析配置。完成之后就可以到浏览器直接访问并进行下载了。
现在为了控制 sftp 授权的用户(erya
)对服务器的权限,让他在连接工具中直接免密码登陆
。
先在 root 用户下生成一对密钥对。
[root@localhost ~]# ssh-keygen -t rsa
然后把公钥传给家目录下改名为authorized_keys
,然后在登陆的时候,使用私钥文件,就实现了免密码登陆。
cp /root/.ssh/id_rsa.pub /home/erya/.ssh/authorized_keys
如果想通过传输的方式将公钥传输过去,那么有两种情况。
# 1,端口默认。
这种情况下,就直接使用 ssh-copy-id 的方式进行传输就好了。
# 2,指定端口。
ssh-copy-id –I .ssh/id_rsa.pub “-p 12345 abc@192.168.66.10”
# 9,sftp 客户端如何使用。
1, 将 / root/.ssh/id_rsa 文件发到本地,然后在 Xftp 的工具栏里导入。
2, 进行 erya 用户登陆的配置,IP,协议,端口,秘钥,用户名。
3, 配置完成,直接点击连接,这样用户就锁定在 upload 目录下了。
这样如果给别人来进行上传,直接让他在客户端,把秘钥文件发给他,就 ok 了。安全又卫生。
现在,上传的文件,与 nginx 所访问到的目录文件保持了一致,只要在域名后边添加相应的文件名字,就可以直接进行下载了,把这样的效果交给服务端开发同学,只需要他这边把链接放到对应的地方就可以啦。