菜单

Linux SFTP

2013年04月24日 - linux

由于采用明文传输用户名和密码,FTP协议是不安全的。在同一机房中只要有一台服务器被攻击者控制,它就可能获取到其它服务器上的FTP密码,从而控制其它的服务器。

当然,很多优秀的FTP服务器都已经支持加密。但如果服务器上已经开了SSH服务,我们完全可以使用SFTP来传输数据,何必要多开一个进程和端口呢?

下面,我就从账户设置、SSH设置、权限设置这三个方面来讲讲如何使用SFTP完全替代FTP。

范例

本文要实现以下功能:

SFTP要管理3个目录:

homepage
blog
pay
权限配置如下:

账户www,可以管理所有的3个目录;
账户blog,只能管理blog目录;
账户pay,只能管理pay目录。
web服务器需求:

账户blog管理的目录是一个博客网站,使用apache服务器。apache服务器的启动账户是apache账户,组为apache组。
账户blog属于apache组,它上传的文件能够被apache服务器删除。同样的,它也能删除在博客中上传的文件(就是属于apache账户的文件)。
账户设置

SFTP的账户直接使用Linux操作系统账户,我们可以用useradd命令来创建账户。

首先建立3个要管理的目录:

mkdir /home/sftp/homepage
mkdir /home/sftp/blog
mkdir /home/sftp/pay
创建sftp组和www、blog、pay账号,这3个账号都属于sftp组:

groupadd sftp
useradd -M -d /home/sftp -G sftp www
useradd -M -d /home/sftp/blog -G sftp blog
useradd -M -d /home/sftp/pay -G sftp pay

# 将blog账户也加到apache组
useradd -M -d /home/sftp/blog -G apache blog

#设置3个账户的密码密码
passwd www
passwd blog
passwd pay
至此账户设置完毕。

SSH设置

首先要升级OpenSSH的版本。只有4.8p1及以上版本才支持Chroot。

CentOS 5.4的源中的最新版本是4.3,因此需要升级OpenSSH。

指定新的源:

vim /etc/yum.repos.d/test.repo
#输入如下内容
[centalt]
name=CentALT Packages for Enterprise Linux 5 – $basearch
baseurl=http://centos.alt.ru/repository/centos/5/$basearch/
enabled=0
gpgcheck=0
# wq保存
执行升级:

yum –enablerepo=centalt update -y openssh* openssl*
# 重启服务
service sshd restart
# 重看版本
ssh -V
# OpenSSH_5.8p1, OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008
升级成功后,设置sshd_config。通过Chroot限制用户的根目录。

vim /etc/ssh/sshd_config
#注释原来的Subsystem设置
Subsystem sftp /usr/libexec/openssh/sftp-server
#启用internal-sftp
Subsystem sftp internal-sftp
#限制www用户的根目录
Match User www
ChrootDirectory /home/sftp
ForceCommand internal-sftp
#限制blog和pay用户的根目录
Match Group sftp
ChrootDirectory %h
ForceCommand internal-sftp
完成这一步之后,尝试登录SFTP:

sftp www@abc.com
#或者
ssh www@abc.com
#如果出现下面的错误信息,则可能是目录权限设置错误,继续看下一步
#Connection to abc.com closed by remote host.
#Connection closed
权限设置

要实现Chroot功能,目录权限的设置非常重要。否则无法登录,给出的错误提示也让人摸不着头脑,无从查起。我在这上面浪费了很多时间。

目录权限设置上要遵循2点:

ChrootDirectory设置的目录权限及其所有的上级文件夹权限,属主和属组必须是root;
ChrootDirectory设置的目录权限及其所有的上级文件夹权限,只有属主能拥有写权限,也就是说权限最大设置只能是755。
如果不能遵循以上2点,即使是该目录仅属于某个用户,也可能会影响到所有的SFTP用户。

chown root.root /home/sftp /home/sftp/homepage /home/sftp/blog /home/sftp/pay
chmod 755 /home/sftp /home/sftp/homepage /home/sftp/blog /home/sftp/pay
由于上面设置了目录的权限是755,因此所有非root用户都无法在目录中写入文件。我们需要在ChrootDirectory指定的目录下建立子目录,重新设置属主和权限。以homepage目录为例:

mkdir /home/sftp/homepage/web
chown www.sftp /home/sftp/homepage/web
chmod 775 /home/sftp/homepage/web
要实现web服务器与blog账户互删文件的权限需求,需要设置umask,让默认创建的文件和目录权限为775即可。将下面的内容写入.bashrc中:

umask 0002
至此,我们已经实现了所有需要的功能。

—————————–
umask 0002
—————————–
一、团队构建环境,文件读写共享
项目代码位于/svn/prj下,通过svn up更新代码,调用ant来编译、部署。那么,prj这个目录,对于每个人都是需要可读写的。
我 们知道,用什么用户登录,新创建的文件宿主,就是当前用户。而默认的文件权限是644(-rw-r–r–),张三从代码仓库中update的文件,或 者编译后生成的class文件,李四是没法删除的。执行ant clear必然不成功,每次都用chmod去修改相应文件,总不是个事,那怎么办呢?
目标很明确:我们希望,开发团队中,每一个开发人员之间的权限是平等的,谁新建的文件都可以被其他人读写。
分解出来是两个事情:
1.目录/svn/prj应该属于开发团队,即一个用户组。这很简单,建立一个组,比如叫dev,使用chown即可
#gruopadd dev
#useradd zhangshan
#useradd lisi
#useradd zhangsan -G dev -g dev
#useradd lisi -G dev -g dev
#chown -R :dev /svn/prj
这里要特别说明一下,-g和-G是有区别的。-G是大家自然理解的,把一个用户加到一个组或者多个组(逗号分隔)里面去。-g呢,则是
设置用户的gid。也就是用户登陆后初始group(initial group)。
使用id zhangsan命令,可以看到,uid=zhangsantest,gid=dev,groups=zhangsan,dev。或者使用groups zhangsan,结果是zhangsan dev
要注意,创建一个用户,默认会创建一个同名的组,如果不加-g参数,gid就是那个组的id,新建文件,组属也是用户同名组。所以在这里,-g和-G都是缺一不可的。
2.更改文件创建的默认权限为664(-rw-rw-r–)。
这里涉及到一个知识,就是umask,umask主要用来控制默认创建文件或目录的权限。可以使用umask命令直接修改。在我们的linux环境中,默认的umask是022。
umask:设置哪位为1,则哪位就没有权限。放开哪位,哪位有权限。但文件例外,最高到666(默认没有执行权限)。目录则可以到777
比如设置umask为022,则目录最高可以到755,umask为002,则最高目录可以到775
解决思路:每个用户登录都会执行一些初始化脚本,可以在脚本中修改用户的umask。
脚本片段如下:
USERGROUP=`/usr/bin/id -Gn $USER`
echo $USERGROUP | grep -q dev
if [ $? -eq 0 ]; then
umask 0002
fi
意思很简单,这里不赘述。要注意的是,Linux中,应该放在/etc/bashrc里面,而不是/etc/profile中。
登录shell配置文件执行顺序
/etc/profile–>/etc/profile.d/*.sh–>~/.bash_profile–>~/.bashrc–>/etc/bashrc
我们应该把这个设置放在最后执行的文件/etc/bashrc的末尾位置,以防止设置被覆盖(实际上,linux的/etc/bashrc文件开头就有一段类似的umask设置)。
要说明一点:控制用户对某个目录的默认读写权限,是没有直接支持的。在实际中,暂时也没必要,如果真有特殊需要,可以通过crontab设置监控进程定时进行修改,也很简单,在此不做说明。
二、普通用户的特权身份
OK,在第一部分中,我们解决了多人文件共享读写,该运行服务器了。不就是tomcat吗,startup一下。事情没想象那么简单,Tomcat运行过 程中,会写日志文件,一开始,简单的把logs目录组属划分给dev,但后来陆续又遇到一系列不同的权限问题。于是反思一下:与其一点点修改运行 Tomcat涉及的那么多文件权限,不如把自己身份临时换一下?这就是我们要说的sudo。
sudo命令就是sudoer用来执行root操作的。sudoer配置,通过visudo来编辑。
visudo实际上就是vi /etc/sudoers的包装版。但用这个命令的最大好处是,它有语法检查。
%dev ALL =NOPASSWORD: /usr/local/tomcat/bin/startup.sh
%dev ALL =NOPASSWORD: /usr/local/tomcat/bin/shutdown.sh
百分号表示组,如果是多个组,用%dev,%dev2
ALL为所有主机。如果要指定主机,可换成某个ip地址。
NOPASSWORD表示不需要sudoer输入密码。
最后为授权执行的命令全路径。
sudoer的配置还有很多,比如可以设置别名等,请读者自行学习。
执行:组员只需要在原有命令前面加上sudo 即可。
如此一来,Tomcat停启问题也解决了。
补充:sudo命令通配符的设置,如果某个目录下的所有命令都可以给sudoers开放,可以使用xxxx/*.sh,但这样一来,使用者必须使用绝对路径执行。而在当前路径也不能使用./xxx.sh。是何原因,待研究。
三、sftp用户的umask设置
似乎万事大吉了。但有一天,发现还是有一些文件没有权限覆盖,为什么呢?后来发现这部分文件,都是使用winscp上传的。
解决办法:
vi /etc/ssh/sshd_config文件,找到SubSystem sftp /usr/libexec/openssh/sftp-server这一行,修改为
SubSystem sftp /usr/libexec/openssh/sftp-server.sh
然后vi /usr/libexec/openssh/sftp-server.sh
添加
umask 0002
/usr/libexec/openssh/sftp-server
chmod 755 /usr/libexec/openssh/sftp-server.sh 即可。
当然,umask 0002这行可以跟上面的策略一致
变成
USERGROUP=`/usr/bin/id -Gn $USER`
echo $USERGROUP | grep -q developers
if [ $? -eq 0 ]; then
umask 0002
fi

四、NFS文件设置问题
A、B 两台服务器,A为NFS服务器,B为挂载服务器。开发中,发现这个目录老是出现权限问题。但查看组属又没什么问题。甚是奇怪。
具体事例:
一 个NFS的源路径,比如是hostA:/share,该目录在hostA上的属于用户组dev,hostB mount了这个目录,看到该目录用户组是一个组号,比如105,其实就是hostA上的dev用户组号。但这个组号,在hostB上并不存在 (hostB上也有一个dev组),如何让hostB上的用户也能读写该目录?最后,终于发现症结所在:两边的组号不一致,而文件的拥有者和组属,本质是 认id不认name的。修改了哪边,都会让另一边无法写,产生了冲突。
解决办法:把两边的组号修改为一致。
1.首先,保证hostB上没有105号的组,如果有,则需要协调一个两边都不产生冲突的组号,可能需要修改两边的组号。
2.组号确定之后,假设105就行,在hostB上执行:groupmod –g 105 dev。变化可以通过/etc/group查看
3.重新设置改组涉及到的文件的组属。
4.属于该组的用户需要重新登录,这样才会生效。
五、root用户的行为限制
权限问题中,还有root的滥用。如果使用root来编译部署,root产生的文件,dev用户又无权访问了。也就是说,既然已经划分好了小组构建目录,每个用户都应该是dev组成员才对。root用户应该只在授权或普通用户无法解决的时候,再切换使用。

发表评论

电子邮件地址不会被公开。 必填项已用*标注