关于DNS和Apache - Apache 2.2 中文版参考手册

Apache HTTP Server 2.2

<-
   致谢 | 译者声明 | 本篇译者:金步国 | 本页最后更新:2006年1月2日 | 获取最新版本

关于DNS和Apache

本文档的涵义用一句话总结就是:不要让Apache在分析配置文件的时候使用到DNS解析。如果Apache在分析配置文件时用到了DNS解析,您的服务器就会发生可靠性的问题(也可能根本无法启动),或者遭致拒绝(偷窃)服务攻击(包括用户可以从其他用户那里偷窃点击)。

top

一个简单示例

<VirtualHost www.abc.dom>
ServerAdmin [email protected]
DocumentRoot /www/abc
</VirtualHost>

为了让Apache功能正常,一个虚拟主机绝对需要以下两部分的信息:ServerName和与该服务器绑定的至少一个IP地址。上述示例没有包括IP地址,于是Apache必须要使用DNS解析来查询www.abc.dom的地址。如果在某些不可预料的情况下,当您的服务器解析配置文件时没有得到DNS的支持,那么这个虚拟主机将不会被配置。它将不会对任何请求作出反应。(在Apache1.2之前的版本,服务器甚至无法启动)。

假设www.abc.dom的IP地址是10.0.0.1,那么考虑以下这个配置片断:

<VirtualHost 10.0.0.1>
ServerAdmin [email protected]
DocumentRoot /www/abc
</VirtualHost>

现在Apache需要DNS对这个虚拟主机进行反向域名解析来确定其ServerName。如果反向解析失败,那么将导致这个虚拟主机功能丧失(在Apache的1.2版本之前,服务器将不能启动)。如果虚拟主机是基于域名的,它将完全不能使用,但如果它是基于IP的,那么它将很有可能工作。然而,如果Apache不得不为一个已经包含了服务器域名的服务器产生一个完整的URL,那么它将可能产生一个无效的URL。

以下是一个可以避免上述两个问题的配置片断:

<VirtualHost 10.0.0.1>
ServerName www.abc.dom
ServerAdmin [email protected]
DocumentRoot /www/abc
</VirtualHost>

top

拒绝服务

拒绝服务主要由(至少)两种形式导致。如果您在运行Apache1.2以前的版本,在上述两种情况下,如果您的任何一个虚拟主机的DNS解析失败,您都会无法启动服务。在一些情况下,DNS解析甚至不在您的控制范围之内。比如说,如果abc.dom是您的一个客户,而且他们自己控制着DNS。那么仅仅是因为他们删除了www.abc.dom这个记录,都会导致您1.2版本以前的Apache无法启动。

另外一种形式就更隐蔽了。比如说下面这个配置片断:

<VirtualHost www.abc.dom>
  ServerAdmin [email protected]
  DocumentRoot /www/abc
</VirtualHost>

<VirtualHost www.def.dom>
  ServerAdmin [email protected]
  DocumentRoot /www/def
</VirtualHost>

假设您已经为www.abc.dom设定了10.0.0.1、为www.def.dom设定了10.0.0.2。更进一步,假设def.dom自己控制DNS。在这种配置下,def.dom可以将所有指向abc.dom的流量据为己。为了达到这个目的,他们只需把www.def.dom的地址解析设置成10.0.0.1就可以了。因为他们控制着自己的DNS服务,所以您无法阻止他们把www.def.dom这个记录指向任何一个IP地址。

然后,所有向10.0.0.1发出的请求(包括用户所有类似http://www.abc.dom/whatever的URL)都将会被def.dom这个虚拟主机所接收。为了更好的理解这一切是怎样发生的,您需要一个关于Apache是怎样将进入的请求分配给它的虚拟主机的深入说明。您可以在这里找到一个完整的文档

top

"主服务器"地址

在Apache1.1中,基于域名的虚拟主机支持需要Apache知道运行httpd的主机的IP地址。可以用全局变量ServerName(如果存在)或者调用C函数gethostname(与在命令行模式下键入"hostname"得到的返回值一样)。接着它就会利用DNS来查找这个地址。目前还没有办法避免这样的查找。

如果您担心这样的查找会因为您的DNS服务器没有启动而遭到失败的结果,您就可以在/etc/hosts中插入一条记录来确定主机名(此文件中应该已经存在这条记录了,否则您的机器可能无法正常启动)。然后,要确认您的机器已经配置为当DNS解析失败的情况下会使用/etc/hosts ,根据所使用的操作系统不同,您可能需要在/etc/resolv.conf/etc/nsswitch.conf两个文件中选择一个进行编辑。

如果您的服务器不必因为其他理由而使用DNS,您也许不必在把HOSTRESORDER环境变量设为"local"的情况下运行Apache。这取决于您所使用的操作系统和解析库。如果您没有使用mod_env来控制环境变量,它还将影响到CGI。强烈建议您查看操作系统附带的man帮助或FAQ。

top

避免这些问题的小技巧

  • VirtualHost中使用IP地址
  • Listen中使用IP地址
  • 确保所有的虚拟主机拥有显式的ServerName定义
  • 创建一个不包含任何页面的<VirtualHost _default_:*>服务器
top

附录:进一步的提示

涉及到DNS的情况都很让人很不舒服。在Apache1.2中,我们努力想让服务器在DNS解析失败的情况下至少保持能够启动,但我们没能做到。在当今重编号成了必须的Internet上面,在配置文件中显式的写明IP地址已经成为不合时宜的行为了。

上述盗窃攻击的解决办法是在一个正向DNS查询后再进行一个逆向DNS解析并将两个结果进行比较。如果不同,就禁用相应的虚拟主机。这个方法需要一个正确配置了的逆向域名解析服务器(因为FTP服务器和TCP封装进行的"双重逆向"DNS处理的普遍应用,这已为大部分管理员所熟知了)。

在某些情况下,如果没有使用IP地址而DNS解析又失败了,那么正常启动一个基于域名的虚拟主机看来是不可能的。一些诸如禁用部分配置文件这样的权宜之计会带来比根本不能启动更遭的不可预测的结果。

随着HTTP/1.1的部署以及浏览器和代理服务器开始支持Host头,我们完全避免使用基于IP的虚拟主机也逐渐成为可能。这种状况下,web服务器也不必在配置时进行DNS的查询。但在1997年3月,这些特性的采用还没有广泛到可以在重要的web服务器应用的地步。