黑客与 / - 您的个人服务器:DNS

作者:Kyle Rankin

在这个时代,让别人为您换油、种植蔬菜、改造房屋和托管服务是很简单和流行的。然而,我认为自己管理这些事情要更有意义、更具教育意义,而且并不十分困难。本专栏是关于如何在您自己的服务器上管理您自己的服务的系列文章的第二篇。在第一篇专栏中,我讨论了如何确保您的家庭网络已准备好托管您自己的服务。在本专栏中,我开始深入探讨主题,并讨论您可以在家设置(并且应该设置)的第一个服务:DNS。

DNS 简要入门

DNS(域名系统)是您每天都在使用的系统,也是互联网严重依赖的系统。互联网上的每个服务器(包括您自己的服务器)都应该有一个公共 IP 地址。自从上个月的专栏以来,您应该已经为您的服务器设置了家庭网络,并且至少有一个可以使用的公共 IP(最好是静态的)。确实,要在互联网上托管许多服务,您真正需要的只是一个 IP 地址;然而,在实践中,只有少数 IP 地址(如电话号码)是普通人会记住的。随着 IPv6 变得普及,这一点将更加真实。DNS 允许您注册域名,并将各个主机名(如 www.example.com 和 mail.example.com)与 IP 地址关联起来。

例如,你们当中有多少人(除了 Katherine)记住了 www.linuxjournal.com 的 IP 地址?如果您想知道 IP 地址,您只需执行一个简单的 nslookup 命令

$ nslookup www.linuxjournal.com
Server:		192.168.0.1
Address:	192.168.0.1#53

Non-authoritative answer:
Name:	www.linuxjournal.com
Address: 76.74.252.198

在本例中,第一段输出告诉我,我正在从 192.168.0.1(我自己的个人 DNS 服务器)的 DNS 服务器获得此答案,并且 www.linuxjournal.com 的 IP 地址目前是 76.75.252.198。本专栏没有足够的空间来描述让我获得该 IP 地址所发生的一切,但本质上,我的 DNS 服务器向互联网上的其他 DNS 服务器询问了该 IP 地址,并随后被重定向到越来越多的 DNS 服务器,直到最终找到知道答案的服务器。如果您对这方面的工作原理的更多细节感兴趣,像DNS 和 BIND这样的书做得很好地解释了它,或者从命令行,您可以运行dig www.linuxjournal.com +trace.

您自己的 DNS 服务器

DNS 看起来像是一项复杂的服务,但设置自己的 DNS 服务器相对简单。现在,有很多不同的 DNS 服务器软件可供选择,它们更容易配置或具有花哨的数据库后端,但对于本文,我将选择旧的支柱 BIND。虽然它不像其他 DNS 服务器那样简单,但一旦您掌握了窍门,它就不会那么糟糕。

BIND 应该为大多数主要发行版打包;但是,每个发行版打包 BIND 的方式略有不同。例如,在 Red Hat 下,您安装 bind 软件包,但在基于 Debian 的系统(如 Ubuntu)下,您安装 bind9。Red Hat 将其核心 BIND 配置文件存储在 /etc/named.conf 中,并将其所有区域文件(包含域(如 example.org)、子域(如 ny.example.org)或可能两者兼有的名称→IP 地址映射的文件)存储在 /var/named 下,而基于 Debian 的系统将 named.conf 和任何区域文件放在 /etc/bind/ 目录下。甚至 init 脚本在两个系统上也是不同的:Red Hat 使用 /etc/init.d/named,而基于 Debian 的系统使用 /etc/init.d/bind9。然而,一旦您克服了这些差异,文件内部的语法应该是相似的。为了简化事情,我将根据标准的 Ubuntu 10.04 LTS 服务器来编写本文的其余部分,以便我们有一些基线。但是,如果您使用不同的发行版,将这些说明调整到不同的文件路径应该不会太困难。

一旦在系统上安装了 BIND,软件包应该会创建一个基本的 named.conf 文件和所有基本目录。在本例中,对于此示例 Ubuntu 系统,默认的 named.conf 实际上将被设置为充当缓存名称服务器。因此,开箱即用,您应该能够使用网络上的其他主机指向此服务器,并且它将能够像使用您的 ISP 的 DNS 服务器一样解析互联网上的其他域。但在本例中,我们想要创建一个 DNS 主服务器。

主 DNS 配置

DNS 主服务器包含自己的区域文件,其中包含名称→IP 地址映射,并且它不必咨询任何其他来源来回答对这些名称的查询。相比之下,DNS 从服务器配置为从 DNS 主服务器加载其所有区域配置。任何未来的更改都在主服务器上进行,并传播到每个从服务器。任何单独的 BIND 实例都可以充当 DNS 主服务器、DNS 从服务器或缓存名称服务器,或同时充当所有这三者(尽管对于任何单独的区域,它只能是主服务器或从服务器,而不能两者兼得)。

对于本例,让我们为 example.org 设置一个 DNS 主服务器,并且此主服务器将具有以下记录

  • ns1.example.org,它指向 123.12.34.56(名称服务器本身的公共 IP)。

  • example.org,它指向 123.12.34.57。

  • www.example.org 也指向 123.12.34.57。

首先,我在 /etc/bind/db.example.org 中创建区域文件(记住 Red Hat 将这些区域存储在不同的位置),并将以下信息放入其中

;
; BIND data file for example.org
;
$TTL 4h
@  IN  SOA ns1.example.org. root.example.org. (
	    2		; Serial
	    604800 	; Refresh
	    86400 	; Retry
	    2419200 	; Expire
	    604800 ) 	; Negative Cache TTL
;
@	IN NS	ns1.example.org.
@ 	IN A	123.12.34.57
www	IN A	123.12.34.57
ns1 	IN A 	123.12.34.56

确保此文件具有与您在 /etc/bind 目录中找到的其他区域文件类似的权限。文件中的第一个非注释行设置 TTL 或生存时间,即远程 DNS 服务器将缓存从您的 DNS 服务器获得的任何答案的默认时间,然后才会再次询问它。您在此处放置的值将有助于确定您所做的更改传播的速度。BIND 接受此字段中的秒数,或者您可以使用速记值,如 1d 表示一天,4h 表示四小时或 20m 表示 20 分钟。我在此处将 TTL 设置为四小时;但是,如果您经常更改记录(或知道您很快要这样做),您可能希望使 TTL 更短。另一方面,如果您发现您几乎从不更改这些值,您可能希望将 TTL 提高到一天,以减少 DNS 服务器上的负载。

需要注意的是,区域文件使用分号而不是行首的井号作为注释。一个常见的错误是在区域文件中放置井号来制作注释,重新加载 BIND,然后想知道为什么您的更改没有生效。当 BIND 看到这样的错误时,它只会跳过该特定区域。

为了保持简单,我将在此处跳过重试、刷新和其他值 - 除非您知道自己在做什么,否则只需将它们保留为这些默认值即可。序列号行用于 DNS 从服务器,我稍后会讨论。但是,在这些值下方,您将看到我用来定义不同记录的语法

@	IN NS	ns1.example.org.
@ 	IN A	123.12.34.57
www	IN A	123.12.34.57
ns1 	IN A 	123.12.34.56

第一个记录以 @ 开头,这意味着它是 example.org 本身的记录。在本例中,它是一个 NS 记录,它定义了我将用于我的名称服务器的主机名。您可以在此处使用您控制的任何主机名(实际上包括不同域上的主机名),但一个流行的约定是为主名称服务器和辅助名称服务器使用像 ns1 和 ns2 这样的主机名。第二个记录也以 @ 开头,只是在本例中,它是一个 A 记录。A 记录是一个基本的 DNS 记录,它将主机名(如 www)映射到 IP 地址(如 123.12.34.57)。在本例中,由于记录以 @ 开头,因此我正在设置 example.org 本身的 IP 地址。接下来的两行定义了另外两个 A 记录,一个用于 www.example.org,另一个用于 ns1.example.org。如果您在本地域名中使用了名称服务器的名称(如 ns1.example.org),请务必添加 A 记录,以便它具有 IP 地址,这一点很重要。

现在我已经创建了我的区域,接下来我需要修改 /etc/bind/named.conf 文件,并在文件末尾添加一个新部分,以指向我刚刚创建的 /etc/bind/db.example.org 文件

zone "example.org" {
	type master;
	file "/etc/bind/db.example.org";
};

文件更改后,我重新加载 BIND,我应该能够将 DNS 请求发送到我的新 DNS 服务器

$ sudo /etc/init.d/bind9 reload
* Reloading domain name server... bind [OK]

$ nslookup www.example.org localhost
Server:		localhost
Address:	127.0.0.1#53

Name:	www.example.org
Address: 123.12.34.56

如果 BIND 重新加载出现问题,它应该会在命令行中告诉您。否则,如果仍然无法工作,您可能需要在您的 syslog 文件(基于 Debian 的系统上的 /var/log/syslog 和 Red Hat 上的 /var/log/messages)中查找线索。

从 DNS 配置

互联网上的许多注册商要求您注册的任何域都至少配置两个 DNS 服务器。这是一个很好的做法,因为如果您只有一个 DNS 服务器并且它宕机,它将有效地使您在该域下的所有服务器都无法访问。这意味着您需要在不同的 IP 上设置第二个 DNS 服务器,最好是在不同的网络上,或者让拥有 DNS 服务器的朋友充当您的主 DNS 服务器的从服务器。无论哪种情况,这都是一个相对简单的过程。假设我的第二个 DNS 服务器的 IP 地址为 98.76.54.32。首先,我将登录到我的主 DNS 服务器,并将新的 NS 和 A 记录添加到我的区域文件

;
; BIND data file for example.org
;
$TTL 4h
@  IN  SOA ns1.example.org. root.example.org. (
	    2		; Serial
	    604800 	; Refresh
	    86400 	; Retry
	    2419200 	; Expire
	    604800 ) 	; Negative Cache TTL
;
@	IN NS	ns1.example.org.
@	IN NS	ns2.example.org.
@ 	IN A	123.12.34.57
www	IN A	123.12.34.57
ns1 	IN A 	123.12.34.56
ns2 	IN A 	98.76.54.32

接下来,我编辑 named.conf,并在 example.org 的配置中添加一行,以便它允许从我的 DNS 从服务器进行区域传输

zone "example.org" {
	type master;
	file "/etc/bind/db.example.org";
	allow-transfer { 98.76.54.32; };
};

最后,我将在第二个服务器上安装 BIND,或者如果它已经存在,我所要做的就是在 named.conf 文件的末尾添加一个新条目,以定义 example.org 区域并告诉此服务器主服务器的 IP 地址

zone "example.org" {
	type slave;
	file "/var/cache/bind/db.example.org";
	masters { 123.12.34.56; };
};

请注意,在本例中,从区域存储在 /var/cache/bind 下。这是基于 Debian 的系统下从区域文件的默认位置。在 Red Hat 下,您会将它们存储在 /var/named/ 下。一旦我在从服务器上重新加载 BIND,它将从主服务器拉取新的区域信息,并且我应该能够对其执行 DNS 查询。

一旦您设置了从服务器,请记住,每当您对主服务器进行更改时,您都需要增加主服务器区域文件中的序列号字段(在我的示例中,它设置为 2,但许多管理员喜欢将其设置为当前日期加上两个额外的数字字段,例如 2010120500)。当从服务器需要知道其区域信息是否是最新的时,它会将自己的序列号与主服务器上的序列号进行比较。如果区域的主服务器序列号较高,则它会复制新的区域信息;否则,它会坚持使用其缓存的内容。

域名注册

一旦您拥有了一个功能正常的 DNS 服务器,剩下的就是告诉全世界使用它。如果您尚未向注册商注册您的域名,请在互联网上找到域名注册服务(这里有太多了,我无法一一列举,但搜索域名注册应该会找到很多)。当您注册域名时,大多数注册商都会允许您使用他们自己的 DNS 服务器来管理您的域名,但您不需要它们!当您到达注册过程中的询问您 DNS 服务器的点时,只需向他们提供您自己的 DNS 服务器的公共 IP 地址(在我的示例中,它将是 ns1.example.org 或 123.12.34.56)。请注意,许多注册商要求您为一个域定义两个 DNS 服务器,因此在这种情况下,请设置一个从 DNS 服务器并将它的 IP 地址也添加进去。一旦您完成注册过程并让新的域名信息有时间在互联网上传播,您将有能力从您自己的机器上为您的 Web、邮件和其他服务器进行 IP 更改。

Kyle Rankin 是旧金山湾区的系统架构师,也是许多书籍的作者,包括官方 Ubuntu 服务器书籍Knoppix HacksUbuntu Hacks。他目前是北湾 Linux 用户组的主席。

加载 Disqus 评论