Random Tech Thoughts

The title above is not random

用 Dnsmasq 搭建自动更新的 DNS 服务器

最近实验室搬家,网络环境全都要自己搭建。技术帝同学vyatta 把我们的一台 x86 服务器配成了 NAT server。vyatta 本身基于 Debian,但做了很多修改,可以通过命令使用统一的方式来配置 DHCP, DNS, NAT, PPTP/L2TP VPN 等等服务,不用自己去学习每一种服务应该如何配置,所以使用起来很方便。(如果你自己配置过 NAT, PPTP 等服务,在 vyatta 上只用几条命令就可以完成配置就会有此体会了。)

vyatta 的问题是对于它设计时支持的网络环境配置起来的确非常方便,但是如果需求超出它的范围,则需要绕过它来自己配置,但由于它不是标准的 Debian,有些事情做起来不太方便。我们使用 vyatta 时就遇到了这样的问题。

我们希望实验室的每台机器配置好自己的 hostname,通过 DHCP 获取 IP 时自动更新 DNS 服务器中对应 hostname 的记录,从而通过名字来实现机器间的互相访问。ISC 提供的 DHCPBIND 就提供了这样的功能。原理是 DHCP 服务器在分配 IP 给 client 之后发送更新 DNS 记录的请求给 BIND 服务器,当然 BIND 需要配置成允许更新 DNS 记录。(动态更新 DNS 在 RFC 2136 中有描述。)

vyatta 使用了一个修改过的 DHCP server,而 DNS 服务器使用了 dnsmasq,似乎这两个服务不能很好的合作来实现我们的需求。实际上 dnsmasq 可以同时作为 DHCP 和 DNS 服务器,所以它可以很方便的实现动态更新 DNS 记录的功能(不需要通过单独的协议),这其实是它的默认行为。所以最后我们选择禁用 vyatta 的 DHCP 服务器,然后将 dnsmasq 配置成同时提供 DHCP 和 DNS 服务。实现这一功能的 dnsmasq 配置文件非常简单,如下:

# Never forward plain names
domain-needed
bogus-priv

# Don't forward request for this domain
local=/example.com/

# listen on eth0 for both DHCP and DNS service
#interface=eth0
# if you want to have VPN access to have DHCP and DNS working,
# it's better to listen on IP address instead of network interface
listen-address=192.168.1.1

domain=example.com

# netmask is 255.255.0.0, so 192.168.1.255 is OK to use
dhcp-range=192.168.1.2,192.168.2.255,24h

服务器端就这些配置,每台机器只要设置好自己的 host,并且在 DHCP 请求中包含自己的 hostname 即可。

使用中发现 Debian 6 在使用 /etc/network/interfaces 来配置网络时,无法更新 DNS 记录,Ubuntu 和使用桌面的 Debian 6 都没问题。查看 dnsmasq 的 DHCP log 发现 Debian 6 的 DHCP client 在 DHCPACK 消息中没有包含 hostname。这篇文章 提到了这个问题。Ubuntu 对 DHCP 客户端打了 patch,默认会在 DHCPACK 中包含 hostname,而 Debian 在使用 networking 来配置时必须要自己配置(使用 NetworkManager 配置网络时正常)。具体方法是在 /etc/dhcp/dhclient.conf,加入如下行:

send host-name "your-host-name";

其实最开始想配置成通过名字互访时有考虑过 zeroconf,但看起来有点复杂,而且实验室 OS X, Linux, Windows 共存,Windows 平台的 zeroconf 自成一套,部署可能不便。倒是 dnsmasq 这个软件小巧好用,解决这个问题非常方便。

Comments