配置安全的共享web服务器(抛砖引玉)

本文所讲的共享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 用户无法自己更改密码,除非自己写个守护程序啥的。这个程序在写的时候要非常小心,因为操作的是系统用户文件,如果遗留有安全漏洞可能会使别人获得其它用户权限。一个折中的方法是写个程序,定期更改密码并通过邮件告知用户,虽不方便但安全性要好一些。

4 thoughts on “配置安全的共享web服务器(抛砖引玉)”

  1. 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, 但文件都是自己的.

    1. 谢谢补充,可以看出一般共享主机,都是用 fcgi、suphp 之类的,这样除了用户权限独立之外,进程也是相对独立的。

      另外,登录后没反应的原因我想到了,由于使用了 chroot 机制,用户的登录 shell 虽然还是 /bin/bash,但chroot后的 / 对应着原来的 /home/friend,里面没有什么 bin 目录,自然登录后就没反应了。

  2. 对. 可以考虑放一些 static binary. 甚至 busybox (需要仔细定制, 静态, 硬链接) 都是可以的.

    程序列表事实上也是挺难把握的, busybox 的列表可以用来参考, 直接把 busybox.static 的硬链接做进去, 硬链接的名称就是程序的名称, 以后想增加删除也是容易的. 你有空可以试试看.

    关于 busybox.static, 有些发行版应该是分开的, gentoo 是两个在一起, debian 系应该只能装 busybox / busybox-static 中的一个.

Leave a Reply

Your email address will not be published. Required fields are marked *