本文所讲的共享web服务器,并非共享文件的服务器,而是多人一起使用的web服务器,各有各自的网站、管理自己的文件,互不干涉,且对系统无影响。鉴于功力较浅,只敢对较信得过的朋友开放这种账号,本文涉及的范围也有限,所以安全漏洞可能还有,请诸位切勿直接用于生产环境。
服务器环境:Ubuntu 8.10, OpenSSH_5.1p1 Debian-3ubuntu1, Apache 2.2.9, PHP 5.2.6-2ubuntu4
登录 – SFTP
传统的 FTP 肯定是不如这个安全,telnet 更不用说了。使用 SFTP 还有一个起始想法是想配置证书自动登录,后来发现 SFTP 客户端(FileZilla)没这功能,就没再作下去,命令行下 scp 的自动登录倒是 和[ ssh 的](279)一样很好配置。
网上很多文章介绍把 sftp 用户限制在 $HOME
目录下的方法,使用的是 sshd 的 ChrootGroups 选项,这个选项在我的版本里没有找到,找到[另外一篇参考文章](http://shapeshed.com/journal/chroot_sftp_users_on_ubuntu_intrepid/)使用的是 ChrootDirectory,也很好用。
创建一个用户组,作为所有 sftp 用户的用户组:
$ sudo groupadd sftp
创建用户,设置密码,并归入 sftp 组:
$ sudo useradd -m friend
$ sudo passwd friend
$ sudo usermod -g sftp friend
为了进一步增强安全性,还可以将用户的登录 shell 设置为 /bin/false
,是个好习惯,但在本例中并非必须,下面的 sshd 设置也会让用户无法登录 shell (我观察的结果)。
$ sudo usermod -s /bin/false friend
下来就要配置 sshd 了,编辑配置文件 /etc/ssh/sshd_config
:
# 修改下面这句
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
然后在此配置文件末尾添加:
Match group sftp
X11Forwarding no
ChrootDirectory %h
AllowTcpForwarding no
ForceCommand internal-sftp
配置含义大概为:凡是 sftp 组的用户,关闭 X 转发,chroot 到 $HOME
目录,关闭 TCP 转发(无法使用隧道了?),强制使用 internal-sftp(这个不明白)。
现在,重启 ssh 服务,用户就只能通过 sftp 访问 /home/friend
下的文件了。
PS: 我发现 sshd 如果配置错误,在 restart 服务的时候会先检查,而不是直接 stop 服务然后在 start 的时候出现错误,搞得服务启不来。大概是考虑到很多人都是远程 ssh 上来进行维护,服务 down 了以后就麻烦了,很贴心的设置。
Apache & PHP
Apache 配置简单,创建 /home/friend/www
目录,约定网站文件都放在这个目录下,然后弄个 Alias 指向就可以了。
但有一个极大的安全隐患需要堵上,用户可以通过编写 PHP 程序,读取系统中任何 www-data 用户有权限访问的文件,包括系统的 shadow 文件,包括 其它用户的网站文件等等。解决这个问题,一种是开启 PHP 的 safe_mode ,安全模式下 PHP 将只能访问 owner 为自己(也就是 www-data)的文件;另外一种是使用 [open_basedir](http://cn2.php.net/manual/en/ini.sect.safe-mode.php),这将限制 PHP 只能打开某一目录树下的文件,并且不可能通过符号链接避开此限制。显然 safe_mode 的副作用太多,后一种方法更适合我的这种情况,配置写到 Apache 的 conf 里就行了:
<Directory /home/friend>
php_admin_value open_basedir "/home/friend/"
</Directory>
注意open_basedir 后面的参数只代表文件路径的前缀,所以要带上末尾的斜杠,明确指出是目录。
不使用 safe_mode 的另外一个原因是在未来的 PHP6 里就要删掉它了。
缺点
最大的缺点就是 sftp 用户无法自己更改密码,除非自己写个守护程序啥的。这个程序在写的时候要非常小心,因为操作的是系统用户文件,如果遗留有安全漏洞可能会使别人获得其它用户权限。一个折中的方法是写个程序,定期更改密码并通过邮件告知用户,虽不方便但安全性要好一些。
1 internal-sftp 的问题可以参见 man sshd_config. 2 一般偶换个端口用 dropbear 做 ssh 的备份, 就算 openssh 挂掉也还剩一个. 3 多用户情况下 lighttpd + 每用户一个 fastcgi 进程, php-fpm 这方面处理的还凑合. 不用 php-fpm 的话也可以 spawn-fcgi (隐患: 需要一个 suid wrapper), spawn 的时候加上 open_basedir 的设置. 4 用户密码的问题没什么太好的解法, 还是开 ssh login 权限吧, 大家共享 chroot, 但文件都是自己的.
谢谢补充,可以看出一般共享主机,都是用 fcgi、suphp 之类的,这样除了用户权限独立之外,进程也是相对独立的。
另外,登录后没反应的原因我想到了,由于使用了 chroot 机制,用户的登录 shell 虽然还是
/bin/bash
,但chroot后的/
对应着原来的/home/friend
,里面没有什么 bin 目录,自然登录后就没反应了。对. 可以考虑放一些 static binary. 甚至 busybox (需要仔细定制, 静态, 硬链接) 都是可以的.
程序列表事实上也是挺难把握的, busybox 的列表可以用来参考, 直接把 busybox.static 的硬链接做进去, 硬链接的名称就是程序的名称, 以后想增加删除也是容易的. 你有空可以试试看.
关于 busybox.static, 有些发行版应该是分开的, gentoo 是两个在一起, debian 系应该只能装 busybox / busybox-static 中的一个.
学习了