by Mark Nielsen (homepage)
关于作者:
Mark 先生是一位将自己的时间都捐献给 GNUJob.com 等事业的自由咨询者,他写了很多的文章和自由软件,并且是 eastmont.net 的一名志愿者。
摘要:
对系统服务进行 chroot 以限制入侵者可能造成的破坏,从而提高系统的安全性。
------------------------------------------------------------
介绍
什么是 chroot?chroot 基本上重定义了一个程序的运行环境。更确切地说,它重定义了一个程序(或登录会话)的“ROOT”目录或“/”。也就是说,对于 chroot 了的程序或 shell 来说,chroot 环境之外的目录是不存在的。
那这样又有什么用呢?如果入侵者入侵了你的电脑,他们就不能看见你系统里所有的文件了。这样,就限制了入侵者可能执行的命令,从而禁止了他们溢出不安全文件的机会。但唯一的缺点是,我认为这不能阻止他们察看网络连接和其他资料。因此,你应做一些本文未深入涉及的事情: 保护网络端口。 察看是否所有的服务都以非 root 权限运行。另外,是否所有的服务都进行了 chroot? 把系统日志转移到其他电脑。 分析日志文件。 分析那些试图探测你的计算机的随机端口的人们。 限制服务所占用的 cpu 和内存资源。 激活用户配额。
我认为(把以非 root 权限运行的服务进行)chroot 可以作为一道安全防线的原因是, 如果入侵者得到了一个非 root 账户,但没有使他们得到 root 权限的文件的话,那么他们只能对所入侵的区域造成破坏。 而且,如果 root 账户是入侵区域大部分文件的拥有者的话,入侵者是没有多少攻击的选择的。显然,如果你的账户被入侵, 那一定是某些地方出问题了,但最好能减少入侵者所能造成的破坏。
请记住 我所做的并不是 100% 正确的。这是我第一次尝试这样做,就算只是部分有效的话,也应该是很容易完成基本的配置的。我想做一个 chroot 的 HOWTO,现在所说的只是一些基本的东西。 怎样把所有的服务都 chroot呢?
好的,让我们先创建一个目录“/chroot”,然后以下面的格式把我们的所有服务都放在它下面:
Syslogd 分别和每一个服务一起运行在 hroot 环境下。 Apache 运行在 /chroot/httpd 下. Ssh 运行在 /chroot/sshd 下. PostgreSQL 运行在 /chroot/postmaster下. Sendmail 运行在 chroot 环境下,但不幸的是,它必须以 root 权限运行。 ntpd 运行在 /chroot/ntpd 下。 named 运行在 /chroot/named 下。
每一个服务都是完全与外界隔离的。
我用来创建 chroot 环境的 Perl 脚本。
下载 Config_Chroot.pl.txt 并更名为 Config_Chroot.pl. 这个 Perl 脚本让你列出所有已安装的服务,查看配置文件,配置服务,并启动和停止服务。通常,这就是你应该做的。
创建 chroot 目录
mkdir -p /chroot/Config/Backup 下载 Config_Chroot.pl.txt 并更名为 /chroot/Config_Chroot.pl 如果你的家目录(home directory)不是 /chroot,请把 Perl 脚本里的 $Home 变量作相应的改变。 下载我的配置文件。
现在,重要的是:我只在 RedHat 7.2 和 RedHat 6.2 上测试过。.
请在 Perl 脚本里作相应的改变以适应你的发行版。
关于 chroot,我写了一遍很长的文章,但有了我的脚本,它变得短了很多。在 chroot 了很多服务之后,我注意到这些服务中需要被 chroot 的文件和配置都很相似。对一个特定的服务来说,判断哪些文件需要拷贝的最容易的方法是查看 man,如果程序要用到库文件,就再键入“ldd /usr/bin/file“。你还可以把你正在安装的服务进行 chroot 并手动启动, 看看出了什么错或查一查它的日志文件。
通常,要安装一个服务,可以这样做:cd /chroot
./Config_Chroot.pl config SERVICE
./Config_Chroot.pl install SERVICE
./Config_Chroot.pl start SERVICE
对 Ntpd 进行 Chroot
Ntpd 是一个时间服务,它使你的计算机以及其它计算机和实际时间同步。把它 chroot 是很简单的。
cd /chroot
# 如果你没有使用我的配置文件,请把下一行的注释去掉。
#./Config_Chroot.pl config ntpd
./Config_Chroot.pl install ntpd
./Config_Chroot.pl start ntpd
对 DNS 和 named 进行 Chroot
已经有了 howto 文件,请看
http://www.linuxdoc.org/HOWTO/Chroot-BIND8-HOWTO.html
或
http://www.linuxdoc.org/HOWTO/Chroot-BIND-HOWTO.html
如果你想用我的脚本 cd /chroot
# 如果你没有使用我的配置文件,请把下一行的注释去掉。
#./Config_Chroot.pl config named
./Config_Chroot.pl install named
./Config_Chroot.pl start named
把 Syslog 和其他服务一起进行 chroot 以及我所遇到的困难。
我想把 syslogd 进行 chroot。我遇到的困难是,syslogd 默认使用 /dev/log 目录,而 chroot 了的服务是看不见这个目录的。因此,用 syslogd 做日志记录就不是很方便了。下面是可能的解决方案。
把 syslogd 分别和每一个服务进行 chroot。我实际上就是这样测试的,而且记录了一些日志。我不喜欢这样做,因为我有一个以 root 权限运行的服务。 看看我们是否能连接到外部日志记录设备。 直接把日志记录到文件上而不是通过 syslogd。这可能是最好的安全选择了,尽管如果被入侵,入侵者可以随意改动日志。 配置 syslogd 来查看几个地方,从而得到所有的服务,你可以用 syslogd 的-a选项来做到。
我的唯一的解决方案是确保 syslogd 分别和每一个服务进行 chroot。我喜欢这样的解决方案,它以非 root 权限在自己的 chroot环境(有些像网络端口)下记录日志。这也许是可行的,但我正在停止我所做的,然后寻求一个更好的解决方案。
如果你不想为每一个服务都配备一个独立的 syslogd,那么当你的系统运行 syslogd 时,请在 syslogd 开始时运行下面命令: syslogd -a /chroot/SERVICE/dev/log
如果有 ssh 和 dns 要运行,那么看上去应该像这样:
syslogd -a /chroot/ssh/dev/log -a /chroot/named/dev/log -a /dev/log
关于 syslogd,我最后想说的是,我希望它能运行在非 root 账户下。我试了几个简单的东西,但都没有成功,于是就放弃了。如果能让 syslogd 和每一个服务一起运行在非 root 账户下,我就会对我的安全措施感到满意了。如果可能的话,最好将日志记录到外部设备上。 对 Apache 进行 Chroot
很简单。一旦我运行它,就可以执行 Perl 脚本。现在,我的配置文件是很长的,因为我必须在 chroot 环境下包括 Perl 和 PostgreSQL 函数库。有一件事要注意,如果你要连接到数据库上,请确保你的数据库服务运行在 127.0.0.1 回环设备上,并在关于 DBI 的 Perl 脚本中指定主机为 127.0.0.1. 下面是我怎样把 apache 永久连接到一个数据库上的例子:
$dbh ||= DBI->connect(@#dbi:Pg:dbname=DATABASE@#,"","", {PrintError=>0});
if ($dbh ) {$dbh->{PrintError} = 1;}
else
{$dbh ||= DBI->connect(@#dbi:Pg:dbname=DATABASE;host=127.0.0.1@#,"","",
{PrintError=>1});}
源地址: http://httpd.apache.org/dist/httpd/
把 apache 编译并安装在你系统的 /usr/local/apache 目录下,然后运行 Perl 脚本。 cd /chroot
# 如果你没有使用我的配置文件,请把下一行的注释去掉。
# ./Config_Chroot.pl config httpd
./Config_Chroot.pl install httpd
./Config_Chroot.pl start httpd
在 httpd.conf 文件里包含以下几行:
ExtendedStatus On
SetHandler server-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
SetHandler server-info
Order deny,allow
Deny from all
Allow from 127.0.0.1
然后,在你的浏览器里输入 http://127.0.0.1/server-status 或 http://127.0.0.1/server-info 并检查!
对 Ssh 进行 Chroot
首先,如果把 ssh 从端口 22 重定向到 2222 就理想了。然后,当你启动 ssh 时,让它在一个非 root 账户下监听 2222 端口。在初始化 ssh 连接时,我们只想让有密码的安全账户连进来,但不做其他任何事情。在他们登录之后,运行在端口 127.0.0.1:2222 的第二个 ssh 程序让它们连接到真正的系统 -- 这第二个 ssh 程序应该只在回环设备上监听。这才是你应该做的。现在我们不打算去做。我们要做的唯一的事情是以这个 chroot 的 ssh 做个例子。上面提到的一个练习就请读者自己完成:让 sshd 运行在非 root 账户下,再安装第二个监听回环设备的 sshd 以使人们连进真正的系统。
此外,我们只要把 ssh 进行 chroot 并让你看一看那样做的结果(如果你只做了这些,你不必观察整个系统)。当然,如果能把日志记录在外部设备上就更好了。我们应该用 OpenSSH,但为了方便(这好像不是一个好的借口),我用的是一个商业的 SSH。
源地址: http://www.ssh.com/products/ssh/download.cfm
在 /usr/local/ssh_chroot 下安装 ssh 并运行脚本。 cd /chroot
# 如果你没有使用我的配置文件,请把下一行的注释去掉。
# ./Config_Chroot.pl config sshd
./Config_Chroot.pl install sshd
./Config_Chroot.pl start sshd
我觉得把 ssh 放在 chroot 环境下的一个真正有益的事情是,如果你用它代替 ftp 服务器,人们在你的区域里就只有有限的权限。 Rsync 和 SCP 在人们上传文件时运行得非常好。我不是很喜欢建立 ftp 服务器让人们登录。很多 ftp 服务器都运行在 chroot 环境下,但我不喜欢他们仍旧传送明文密码。
把 PostSQL 进行 Chroot
这几乎和 perl 一样简单,除了它需要一些额外的函数库。总的来说,这并不难做。我必须做的一件事是把 PostgreSQL 放在网络上,但仅仅是放在回环设备上。因为它是被 chroot 了的,所以其他已经 chroot 了的服务是不能和它接触的,就像web服务器 apache 一样。我把 Perl 编译进 PostgreSQL 里去了,因此我必须在我的配置文件里加很多 Perl 的东西。
源代码: ftp://ftp.us.postgresql.org/source/v7.1.3/postgresql-7.1.3.tar.gz
把 apache 编译并安装在你系统里的 /usr/local/postgres 目录下。然后运行 Perl 脚本。 cd /chroot
# 如果你没有使用我的配置文件,请把下一行的注释去掉。
# ./Config_Chroot.pl config postgres
./Config_Chroot.pl install postgres
./Config_Chroot.pl start postgres
把 Sendmail 进行 Chroot
请执行我的 Perl 脚本。
cd /chroot
# 如果你没有使用我的配置文件,请把下一行的注释去掉。
# ./Config_Chroot.pl config sendmail
./Config_Chroot.pl install sendmail
./Config_Chroot.pl start sendmail
现在你发现什么了?是的,他仍旧以 root 账户运行。而且,当sendmail 启动的时候,程序 /etc/rc.d/init.d/sendmail 会重新建立一些文件。我的脚本并没有解决这个问题。无论何时,如果你在 /etc/mail 下做了任何改动,请把改动过的文件拷贝到 /chroot/sendmail/etc 目录下。你还必须把 /var/spool/mail 指向 /chroot/sendmail/var/spool/mail,以使 sendmail 程序和用户(当他们登录进来的时候)看到的是相同的文件。
好在你随时可以发送邮件,当你收信的时候才会出问题。因此,我可以把 sendmail 和 apache 一起安装而不出问题。我的一些 Perl 脚本会向外发送邮件,所以我要把 sendmail 程序拷贝到 apache 的 chroot 环境下。 关于 Chroot 的其他一些事情。
下面是我的观点:
你的机器上包括 sendmail, ssh, apache, postgresql, syslog 在内的所有服务都必须运行在 chroot 环境下。 每一个服务都必须以非 root 账户运行(你也许需要把已受保护的端口重定向到未受保护得端口。这包括 sendmail 和 syslog。 日志应该远离现场。 对每一个服务都实行磁盘配额,以限制入侵者所能占用的磁盘。当磁盘已写满时,你应该在回环设备上为某些服务安装文件系统。 所有不需改动的文件的拥有者应该是root账户。
现在,说到 sendmail 和 syslogd,我仍然认为他们不应运行在 root 账户下。 对于 sendmail,这也许是可能的,但我发现让它运行在非 root 账户下是极其困难的,至少我还没有成功过。 我想,sendmail 不能运行在非 root 账户下应是一个很严重的错误。虽然我知道让它运行在非 root 账户下很困难, 但我认为所有的困难都是可以解决的。只要解决了文件的许可权问题,我觉得 sendmail 是不必以 root 权限运行的。 我肯定是忽略了什么东西,我不相信这些障碍是不可征服的。
至于 syslog,我还没有试过,但我认为应该以非 root 账户去记录日志,我想这应该是可行的。至少我可以为每一个服务在 chroot 的环境下记录日志。
所有的服务都要运行在非 root 账户下,甚至是 NFS。请记住,是所有的服务。 建议
请运行两个 sshd 守护进程,并进行二次登录。 设法使 sendmail 或其他邮件程序运行在非 root 账户下。 删掉 /lib 下不需要的函数库。我只是拷了我需要的函数库在上面。其实你不需要其中的大部分。 请用 syslogd 进行远程日志记录,看看我们是否能让 syslogd 连接到网络端口上并得到运行在回环设备网络端口上的所有服务的日志。 看看能否使 syslogd 运行在非 root 账户下。
结论
我觉得对所有的服务来说 chroot 都是那么酷,我想,不能让所有的服务都运行在非 root 账户的 chroot 环境下应该是个很大的错误。我希望主要的发行版应该做到这一点,当然,也希望其它发行版做到。Mandrake 以兼容 RedHat 起家并发展,因此,人们可以仿效 Mandrake ,在其他人的基础上对 chroot 进行扩展。我认为这是可行的,因为在 GNU/Linux 里,没有什么会阻止你重做其他人的工作。如果某个公司想 chroot 所有服务并为人们创建了一套容易管理 chroot 了的服务的环境,那么它就拥有了一个理想的发行版。记住,Linux 正趋向主流,人们不想再看见命令行,因此如果每件事都可以在 gui 的环境下去做,人们就不需要了解内部的构造,并且不需要知道到底是什么在运行,他们只要能配置并知道这是行之有效的就行了。
我绝对支持让所有服务都运行在非 root 权限的 chroot 的环境下,任何不能做到这一点的发行版,我都不会考虑在生产环境中使用它。我正使所有的服务都运行在 chroot 环境下,尽我的可能使越来越多的东西这样运行 -- 最终,我会达到我的理想。
我打算为 chroot 写一个 HOWTO。我正发送请求,希望某个人能够把我这篇文章转换成 LyX 格式,以便它可以放到 Linux 得 HOWTO 上。 参考书目
如有变动,请见http://www.gnujobs.com/Articles/23/chroot.html