最近遇到这样一个需求:客户端向服务器传送文件,传送完了以后执行一个服务器端的脚本处理这些文件.
向服务器传文件,考虑到认证安全的问题,直接就忽略了ftp.因为服务器是linux系统.ssh服务是必开,所以很自然的将研究的方向锁定在了sftp.于是自然而然的就选择了笔者最熟悉的工具:winscp.你还真别说,winscp果然不负重望.用winscp四年了还真不知道winscp还可以执行服务器端命令.如图:
![](../p_w_upload/201002/201002071265524764234.jpg)
当然这个"执行脚本"是我自定义的命令,开始的时候还一些命令像tar,untar,touch之类的,被我删掉了(也是到这时候才知道可以用这个工具直接压缩和解压文件).
流程跑通了.于是开始考虑细节问题.虽然客户端是受信任的.但是保不齐哪天中个***啥的.于是准备在服务器端限制权限,将用户锁定到它的目录里.花了多半天时间研究sftp的chroot终于弄明白了怎么回事儿.特分享以下细节:
sshd_config的配置:
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
Match User a
ChrootDirectory /chroot
注释掉原来的Subsystem一行,添加以下三行就可以了.Subsystem指定sftp的处理方式.Match在sshd_config中用来指定条件的,后面可以跟group也可以跟ip,也可以三者或者两者同时出现.要注意的是,match所匹配的用户受match以后的语句影响,直到文件尾或者下一个match.ChrootDirectory就是指定匹配的用户登陆以后所在的目录了,这里还可以加%u和%h分别指代用户名和家名.然后再mkdir /chroot就可以了.是的这样就可以了,网上传来传去的做法是在ChrootDirectory下面还加三行:
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal_sftp
难道他们就真没搞明白ssh的sftp工作原理吗?当一个用户登陆系统,无论是用ssh还是sftp,ssh服务先对这个用户进行认证,认证通过以后就会检查match里有没有这个用户,有的话match以后的语句都会对这个用户生效.这个时候当指定ChrootDirectory.ssh会对匹配的用户进行choot的操作.以上面的配置为例,当a用户认证通过以后,他的home目录会限定在/chroot这个目录,这个时候a用户如果是用的sftp协议登陆是没问题的.但是如果a用户使用的是ssh协议,将用户的home锁定在/chroot,会再试图给用户加载给a用户指定的shell,比如说是/bin/bash,而这个时候a用户的/是/chroot,所以ssh试图在/chroot下找/bin/bash,即:/chroot/bin/bash,这个路径肯定是不存在的,所以用户a用户ssh协议登陆根本就不会登陆成功!
root@rainbird10:~# tail -n 1 /etc/passwd
a:x:1001:1001:,,,:/home/a:/bin/bash
root@rainbird10:~# ssh a@localhost
/bin/bash: No such file or directory
Connection to localhost closed.
root@rainbird10:~# sftp a@localhost
Connecting to localhost...
sftp> pwd
Remote working directory: /
sftp> cd ..
sftp> pwd
Remote working directory: /
sftp>
也就是说经过以上的设置,匹配的用户只能使用sftp并锁定到指定的目录.而tcp转发和X11转发都是需要有权限登陆到系统才可以实现的功能,不知道加上有啥意义.
另,我的ssh版本:
root@rainbird10:~# ssh -V
OpenSSH_5.1p1 Debian-5ubuntu1, OpenSSL 0.9.8g 19 Oct 2007
写到这里,权限是限制严格了,笔者也惊喜的发现,再用winscp上传完文件不能执行脚本啦!哈哈,想想也是,都没有权限登陆还执行啥脚本呢.哎,安全和复杂总是彼增我长的.这时候如果想让用户可以登陆的话,可以在/chroot下面给用户再建立简单的bash环境,但是这样已经偏离的初衷.因为即使用户能登陆又能咋样?它执行脚本的时候也只能操作/chroot里的东西,不会影响系统文件.这样虽然锁定了用户目录,但是一点意义也没有.另外linux本身就是个多用户的系统,不发挥它多用户的优势而再搞'子系统'或者说'监狱'环境,有啥意思呢.
既然说到这里了,就再补充一下ftp的知识吧.笔者最熟悉的两个ftp分别是vsftpd和serv_u.随着技术的不断进步,笔者惊喜的发现这两个ftp也都支持加密连接了.vsftpd呢,虽然可以锁定用户目录,但是却不能自定义客户端要执行的命令.而serv_u,可以锁定目录,如果也可以执行系统命令,但是这时候要增加用户的执行权限.但是又不能限制用户所有执行的命令,这样无疑是给自己的服务器安全留个祸口,另外为了实现个小需求而将服务器换成windows实在有点不甘.当然当你看到这篇文章的时候已经有完美解决方案了:)
转载于:https://blog.51cto.com/rainbird/275162