推荐阅读
BIND 官方配置项文档
How To Configure BIND as a Private Network DNS Server on Ubuntu 14.04
BIND9 管理员参考手册
BIND 相关资料
段海新的论文
DNS 简介
DNS 是 Domain Name System(域名系统)的简称,DNS 是一个分层的分布式命名系统,用于连接到互联网或专用网络的计算机,服务或其他资源。它将各种信息与分配给每个参与实体的域名关联起来。
简单来说其最大的功能就是将域名翻译成 IP 地址,例如实验楼的 IP 地址就是一串毫无规则的数字,非常不好记忆,想得起实验楼但是想不起它的 IP 地址。但是域名与站点的意义是相关联的,便于记忆。想起实验楼,就能想起它的域名是 www.shiyanlou.com。
举一个不恰当的例子,人与人之间通电话拨电话的时候,都是通过名字查找电话本中的电话号码,然后直接拨通,电话号码是无逻辑的一串数字,名字是有意义的。
人的姓名是由姓氏与名字构成的,同样域名也是由多个部分构成的。构成域名的每个部分称为一个区域(zone),主要是这样分级的:主机名.二级域名.顶级域名.
不同域直接通过 . 来分割,域名与国外人命名一般,名在前,姓在后,越是大的域越在后面。也就是说靠前的是后面的子集,最右边的是根域可以忽略不写(因为其无名,nameless),在顶级域名的点后面,根域紧接着的就是顶级域名(top-level domains),紧跟着的就是二级域名(second-level),就这样依次类推,在 DNS 的配置时我们需要留着顶级域名后面的 .。
在平时使用的时候因为浏览器会帮助我们自动填充,所以我们可以忽略不写,例如 www.shiyanlou.com 不用写成 www.shiyanlou.com.。
主机名:一般代表公司或者组织的主机名或者某个服务名,一般在最左边。例如 www.shiyanlou.com 中 www 是三级域名也是主机名了,一般这样的比较常见
二级域名(second-level domains):一般代表公司或者组织的名字。例如 www.shiyanlou.com 中的 shiyanlou,例如 www.baidu.com 中的 baidu
顶级域名(top-level domains,TLDS):一般代表的是该公司或者组织在社会中的某个领域,或者所说的国家。在顶级域名中包含两种:
通用顶级域名(generic top-level domains,gTLDs):通用的顶级域名代表的便是在社会中的某个领域,例如 com 表示的是商业,edu 表示的教育机构,gov 表示的政府机构,org 表示的组织机构(例如开源组织什么的)
国家代码顶级域名(country code top-level domains,ccTLDs):国家代码顶级域名显然就是代表所属国家了,例如 cn 代表的是中国,jp 代表的是日本,ca 代表的是加拿大等等
当然 gTDLS 与 ccTLDs 不是说只能用一个,例如南开大学的域名 www.nankai.edu.cn。
DNS 解析
上一节中我们了解到了域名是什么,域名的命名规则,接下来我们将简单地了解一下 DNS 是如何将一个域名解析成 IP 地址,使得我们的浏览器或者其他工具能够访问到我们需要的服务。
我们通过下图来了解整个过程:
image.png
浏览器首先查看其自己的解析记录缓存:
若是缓存记录中存在域名所对应的 IP 地址,则直接使用该 IP 地址
若是缓存记录中不存在该域名的相关记录则进入下一步
查找系统的 DNS 解析缓存,因为 DNS 每次查询的记录都会记录在缓存在中,以免再次查询
在 Windows 中系统启动时便会加载位于 C:\windows\system32\drivers\etc\ 目录中的 hosts 文件于 DNS 缓存中,所以系统在查看 DNS 解析缓存时也等同于在查看 hosts 文件中的记录(在 windows 中并不会直接查询 hosts 文件,而是通过缓存的方式间接查看)
Linux 中的 hosts 文件位于 /etc/hosts,其与 Windows 中使用 hosts 类似,但具体实现方式不同
注意:hosts 文件是 DNS 的前身,早期电脑的数量还很小,一个文件列表中的域名与 IP 的对应足以应付,只是到了后期不便更新维护以及数量大大增加,所以诞生了 DNS 分布式的数据库。
若是在系统的 DNS 解析缓存中也未能找到相关的记录,此时便会去请求系统中设置的 DNS 服务器(系统中设置的 DNS 服务器可能是路由器分配的默认,也可能是自己设置的权威机构的,也可以能运营商自己的)
部分路由器会有 DNS 解析的缓存,此时会在路由器中查询
若还是没有便会将查询的请求交给 ISP 的 DNS 缓存服务器
依旧没有查询到相关的记录便会开始递归搜索
由本地 DNS 服务器或者你配置的服务器将相关的请求转发给根域服务器
根域服务器查询相关的顶级域服务器,然后将请求转发给相关的顶级域服务器
顶级域服务器查询相关的二级域服务器,然后将请求转发相关的二级域服务器
最后将查询结果返回给主机
若还是没有相关记录则访问失败
注意:大部分的请求基本在运营商处可以得到满足,在中国没有 IPv4 的根域,只有镜像。
DNS 解析优先级
在上文中我们提到早期没有 DNS 服务器存在的时候使用的是 hosts 文件,到后期才出现了 DNS 服务器,新的服务方式提出并不代表老得服务方式被彻底替换,hosts 文件的方式因为快速、小巧而被保留了下来。
在 Linux 中我们可以通过 /etc/nsswitch.conf 配置文件修改 DNS 查询的顺序。
通过 sudo vim /etc/nsswitch.conf 打开该配置文件,往下查看就可以看到这样的配置:
#hosts: db files nisplus nis dns
hosts: files dns myhostname
这里的 files 代表的就是 /etc/hosts 文件,dns 代表的是系统配置的 DNS 服务器地址。所以在 Linux 中默认是先查询 hosts 文件中的记录,然后再请求 DNS 服务器。
hosts 文件
因为 hosts 文件在本地相比于请求 DNS 服务器的方式快速,所以得到保留。
我们通常会在 hosts 文件中存放常用的 DNS 记录与开发中测试使用的服务器记录。
hosts 文件的记录格式非常的简单:
IP 地址 域名或者 hostname
例如我们当前机器中的 hosts 文件 cat /etc/hosts:
第二行中 ::1 是 IPv6 的本地地址表示方式,类似于 IPv4 中 127.0.0.1 后面紧跟着的就是主机名。
后续的记录中记录着内网中的地址与主机名的映射关系,我们可以将测试服务器的 IP 地址与测试域名映射关系存放于此,这种记录是不会放在公共 DNS 服务器中,一般存放于本地 DNS 或者 hosts 中。
DNS 服务器配置文件
系统设定的 DNS 服务器配置文件位于 /etc/resolv.conf:
image.png
nameserver 后面对应的便是内网中的 DNS 服务器地址,一般会配置两个,防止一个不可用而导致无法域名解析。
DNS 搭建
切的理论都是为了帮助我们更好的理解软件中的各项配置,以及在出问题时的进行调试,但是仅仅只有理论是不够的,我们需要通过 DNS 的搭建来进一步的了解。
DNS 的选用
DNS 的使用方案有许多,常见的开源软件有:
BIND:全名为 Berkeley Internet Name Domain,是早在 1980 年左右有 Berkeley 大学公开出来的 DNS 服务实现,也是使用最为广泛的方案。后由 ISC 基于 BIND 重写发布 BIND9
PowerDNS:PowerDNS 由 C++ 实现于 1990 年末,起源一个商业软件于 2002 年开源,相对于 BIND 在数据库选用上与集群上功能更多更灵活
CoreDNS:由 SkyDNS 进化而来,主要作为一种可插拔的中间件
DNSpod-sr:一款由国内服务商开源的一套 DNS 的实现
此次我们将选用最为成熟、拥有良好 License 的 BIND9 来搭建属于我们自己的 DNS 服务器。
DNS 的安装
安装和配置 BIND
sudo apt-get update # update 可能会报两个警告,可以忽略
sudo apt-get install -y bind9 bind9utils bind9-doc
激活 IPv4 Mode
在继续配置 DNS 服务器之前,先修改一下 bind9 service 参数文件,设置 BIND 为 IPv4 Mode:
sudo vi /etc/default/bind9
把 "-4" 添加到 OPTIONS 变量,如下所示:
OPTIONS="-4 -u bind"
确定主 DNS 服务器
一般都会设置两个 DNS 服务器,一个主要的,一个备用的,这次的实验受实验环境的限制,我们只做主服务器。 首先查看本机的 ip 地址:
ifconfig -a
我的 ip 地址是192.168.42.5,每个人的是不一样的。然后获取几个有效的内网 ip ,可以试着去 ping 一下,我找的内网 ip 是 192.168.42.1。
ping -c 3 192.168.42.1
DNS 服务器的配置
BIND 的配置由多个文件组成,这些文件包含在主配置文件中named.conf。这些文件名以“named”开头,因为这是 BIND 运行的进程的名称。我们将开始配置选项文件。
cat /etc/bind/named.conf
image.png
有关各配置详细解释可参考 BIND 官方配置项文档
配置选项文件
打开named.conf.options文件进行编辑:
sudo vi /etc/bind/named.conf.options
在现有的文档之上,添加一个新的 ACL 块并命名 "trusted",我们把之前找到的内网 ip 添加到可信客户端列表里,并称为 ns1 ,只允许它们查询 DNS 服务器,提高安全性。
acl "trusted" {
192.168.42.5; # ns1 信任的名单
};
options {
directory "/var/cache/bind";
// If there is a firewall between you and nameservers you want
// to talk to, you may need to fix the firewall to allow multiple
// ports to talk. See http://www.kb.cert.org/vuls/id/800113
// If your ISP provided one or more IP addresses for stable
// nameservers, you probably want to use them as forwarders.
// Uncomment the following block, and insert the addresses replacing
// the all-0's placeholder.
recursion yes; # enables resursive queries
allow-recursion { trusted; }; # allows recursive queries from "trusted" clients
listen-on { 192.168.42.5; }; # ns1 private IP address - listen on private network only
allow-transfer { none; }; # disable zone transfers by default
forwarders {
114.114.114.114; # 当本地的 dns 服务器中找不到记录时向上查询
};
//========================================================================
// If BIND logs error messages about the root key being expired,
// you will need to update your keys. See https://www.isc.org/bind-keys
//========================================================================
dnssec-validation auto;
auth-nxdomain no; # conform to RFC1035
listen-on-v6 { any; };
};
注意 ip 地址根据你自己的 ip 地址填写。
按 esc ,然后输入 :wq 保存并退出 named.conf.options,通过上面的设置只有信任的主机才能查询 DNS 服务器,其他主机不能。
上述配置详解
从配置文件中我们可以看出配置文件的主要格式是:
声明 {
配置参数;
配置参数 {
子配置项;
子配置项;
}
.......;
.......;
}
通过系统提供的配置文件模版来了解常用的配置参数:
声明的参数主要有这样的一些配置:
options 的配置
在 options 中主要配置了一些全局的参数,例如监听的端口、服务的目录、保存文件的名字与路径等等,在默认的配置文件中主要分三个部分:
1.named 服务运行上的配置
image.png
2.控制命令 rndc 运行后产生文件的目录配置:
image.png
3.named 服务运行的安全问题:
image.png
注意:DNSSEC 即 DNS Security Extension,是 DNS 在安全上做的扩展,以应对 DNS 欺骗攻击、缓存污染等一些现有的问题,其原理与产生原因推荐 段海新的论文,讲解的非常详细。
logging 的配置
主要配置日志的日志类别与输出通道,日志类别能够帮我们过滤出想要的部分日志,通道指定我们日志输出的位置,通常分别使用 category、channel。
在 channel 中:
file:定义错误日志输出的文件名与目录
serverity:定义日志的级别
zone 的配置
域的定义,配置对于请求不同域的处理类型。
除此之外还有一些常用的声明配置:
从上述的解释中我们大概了解了默认配置模板中各配置项的意思,每种声明中都有非常多的子配置项,可以非常灵活的配置,我们不会注意讲解其意思与部分高级用法,有兴趣的同学可以查看推荐阅读中的 BIND 官方配置项文档
配置本地文件
打开 named.conf.local并编辑:
sudo vi /etc/bind/named.conf.local
我们修改配置文件,完成后如下,在配置文件中添加了 正向解析和反向解析 的文件在系统中的位置,简单的说,正向解析就是根据域名查 ip,反向就是根据 ip 查域名。
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "shiyanlou.example.com" {
type master;
file "/etc/bind/zones/db.shiyanlou.example.com"; # zone file path
};
zone "168.192.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.192.168";
};
注意,反向区域名称以 168.192 开头,即 192.168 反转。
上述配置详解
在 zone 中主要的配置项有:
其中 type 的四个值的意义是:
hint:当本地找不到解析时可查询根域名服务器
master:设置为主域名服务器
slave:设置为次域名服务器
forward:定义转发的域名服务器
添加完成后,保存退出。这样我们在 BIND 我们就有了指定的文件,接下来我们就编写正向解析和反向解析的域文件。
创建正向解析域文件
正向解析:通过主机名获取其对应的广域网 IP 地址,我们以 "host1.shiyanlou.example.com" 为例来编写来这个文件。
sudo mkdir /etc/bind/zones
我们根据现有的域文件db.local,来复制一份作为db.shiyanlou.example.com 编辑这个正向解析文件:
sudo cp /etc/bind/db.local /etc/bind/zones/db.shiyanlou.example.com
sudo vi /etc/bind/zones/db.shiyanlou.example.com
我们在原来文件的基础上,修改了很多,具体如下:
;
; BIND data file for local loopback interface
$TTL 604800
@ IN SOA ns1.shiyanlou.example.com. admin.shiyanlou.example.com. (
3 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
;
; name servers - NS records
IN NS ns1.shiyanlou.example.com.
; name servers - A records
ns1.shiyanlou.example.com. IN A 192.168.42.5
host1.shiyanlou.example.com. IN A 192.168.42.1
tips:如果直接粘贴到环境会出现乱序,粘贴前请先设置:set paste后再进行粘贴。
注意上面加点的地方不要漏写
ip 地址根据自己的实际地址填写。
创建反向解析域文件
反向域名解析与通常的正向域名解析相反,提供 IP 地址到域名的对应。 IP 反向解析主要应用到邮件服务器中来阻拦垃圾邮件,特别是在国外。多数垃圾邮件发送者使用动态分配或者没有注册域名的 IP 地址来发送垃圾邮件,以逃避追踪,使用了域名反向解析后,就可以大大降低垃圾邮件的数量。
在之前的 named.conf.local 的文件里我们写了一个反向域名解析的文件名db.192.168,现在来编写它:
sudo cp /etc/bind/db.127 /etc/bind/zones/db.192.168
sudo vi /etc/bind/zones/db.192.168
文件的具体内容如下:
;
; BIND reverse data file for local loopback interface
;
$TTL 604800
@ IN SOA shiyanlou.example.com. admin.shiyanlou.example.com. (
3 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
; name servers
IN NS ns1.shiyanlou.example.com.
; PTR Records
5.42 IN PTR ns1.shiyanlou.example.com. ; 192.168.42.5
1.42 IN PTR host1.shiyanlou.example.com. ; 192.168.42.1
tips:如果直接粘贴到环境会出现乱序,粘贴前请先设置:set paste后再进行粘贴。
ip 地址根据自己的实际地址填写。
PTR 首位根据后面的 ip 反转。
正反向解析域文件详解
在 zone file 中,每一条映射值为一条记录,每条记录都会有他的记录类型,针对不同的记录会有不同的格式,首先我们来简单了解一下记录类型的常用种类:
1.A 记录主要便是域名与 IP 地址这两个信息,所以格式为:
hostname IN A IP-address
# 该记录表示访问 www.test-shiyanlou.com 解析为 10.29.113.73
www IN A 10.29.113.73
# 该记录表示访问 test.test-shiyanlou.com 解析为 10.29.113.73
test IN A 10.29.113.73
# 等同于上一条记录
test.test-shiyanlou.com. IN A 10.29.113.73
从上述的例子中我们便可看出在写 hostname 是可以省略区域名 test-shiyanlou.com. 的部分,这是因为配置文件中通过 zone 去声明这个域,所以在其他记录中也是同样的效果。
2.NS 记录指出该域名的 NS 服务器,其格式为:
IN NS nameserver-name
例如:
IN NS dns1
# 等同于
test-shiyanlou.com. IN NS dns1.test-shiyanlou.com.
# 但若是这样指定必须指出 dns1 的 A 记录
dns1 IN A 10.29.113.73
3.MX 记录为 Mail Exchange 的缩写,也就是邮件记录:
注意:
邮件记录的域名必须是使用 fully qualified domain name(FQDN),也就是完整的域名,不能像之前那般省略。
邮件增加了一个 preference-value 值来指定该记录的优先级。
IN MX preference-value email-server-name
# 例如优先级为 5 的 mail.test-shiyanlou.com.
test-shiyanlou.com. IN MX 5 mail.test-shiyanlou.com.
# 当然该记录的相关 A 记录必须存在
mail IN A 10.29.113.73
4.PTR 记录为反向解析记录,将 IP 翻译成域名:
# 格式为
last-IP-digit IN PTR FQDN-of-system
# 例如在 113.29.10.zone 配置文件中,named 中我们声明了,所以可省略 113.29.10-in-addr.arpa
73 IN PTR localhost.
# 完整表示为
73.113.29.10-in-addr.arpa. IN PTR localhost.
因为我们此处是配置的小网段,只用配置一位,若是面对大网段则写两位、三位即可。
5.CNAME 为机器的别名
# 其格式为
alias-name IN CNAME real-name
# 例如
server1 IN A 10.0.1.5
www IN CNAME server1
在上述例子中表示 server1.test-shiyanlou.com 将会被解析到 10.0.1.5,而 www.test-shiyanlou.com 会被解析到 server1.test-shiyanlou.com 也就是 10.0.1.5。
6.SOA 记录表示的是域管理服务器
除了一些命令放在 zone file 的开头,所有记录的第一条记录应该为 SOA 记录,它的格式如下:
@ IN SOA primary-name-server hostmaster-email (
serial-number
time-to-refresh
time-to-retry
time-to-expire
minimum-TTL )
其中 @ 表示的是本机意思,等同于 ORIGIN 代表的值为我们在声明中所自定义域的名字。
例如在 test-shiyanlou.zone 文件中其 ORIGIN 为 113.29.10.in-addr.arpa.。
当然我们可以在配置文件的开头指定该值:
$ORIGIN test-shiyanlou.com.
其中 primary-name-server 表示的是主要的域名服务器的域名,例如 dns.test-shiyanlou.com.。
其中 hostmaster-email 表示的是建立服务器的负责人邮件地址,因为 @ 在此处有特殊意义所以不能直接使用,需要用 . 代替,例如 shiyanlou@qq.com 需要改成 shiyanlou.qq.com。
其中 serial-number 是指定的一个同步序列号,每当 zone file 变化的时候该值便会递增,slave 便知道该同步,该重新加载 zone file 了。
其中 time-to-refresh 是指 slave 多久会主动检查 serial 的值,以便更新 zone file。
其中 time-to-retry 是指 slave 若是连接 master 失败,多久之后会再次尝试。
其中 time-to-expire 是指 slave 若是一直连接 master 失败,多久之后会放弃。
其中 minimum-TTL 是指定最小清除 cache 的时间。
注意:时间的单位都是秒
检验 BIND 配置文件语法是否错误
运行下面的命令检验 named.conf* 有没有语法错误:
sudo named-checkconf
如果没有报错则编写是正确的,如果报错了,那就根据报的错误去修改文件。运行下面的命令查看正向解析和反向解析文件是否正确:
sudo named-checkzone shiyanlou.example.com /etc/bind/zones/db.shiyanlou.example.com
sudo named-checkzone 168.192.in-addr.arpa /etc/bind/zones/db.192.168
image.png
做到这里,离成功已经不远了,我们重启 BIND service:
sudo service bind9 restart
image.png
DNS 客户端配置
打开文件resolv.conf:
sudo vi /etc/resolv.conf
编辑为:
options timeout:1 attempts:1 rotate
nameserver 192.168.42.5 # 这里也要根据自己的实际 IP 配置
好了,接下来可以去检验 DNS 服务器是否可以正常运行了。
排错以及验证
排错
使用 named -g 可以让 dns 服务器在前台运行,并输出所有信息到屏幕,在里面可以看到错误信息。
验证
测试我们的 DNS 服务器是否可以正常运行,使用 nslookup 命令来查询你的服务器,(若使用其他的客户端, ip 地址需要加入到 "trusted" ACL 里面)。先测试正向解析,通过输入网址找到 ip 地址,运行下面的代码:
nslookup host1.shiyanlou.example.com
image.png
再测试反向解析,通过 ip 地址找到它的网址。如果你的反向域名文件写错了,或者放置的位置不对,就会报错,可以在上文重新看看操作
nslookup 192.168.42.1
image.png
好了,到此为止,一个简单的 DNS 服务器就搭建好了,你可以试试添加更多的 ip 地址,快来试试自己的 DNS 服务器吧!
参考资料
How To Configure BIND as a Private Network DNS Server on Ubuntu 14.04
BIND9 管理员参考手册
鳥哥的 Linux 私房菜
BIND 相关资料
网友评论