一、DNS 工作原理
- DNS 本地解析,优先级最高,Linux 的目录是
/etc/hosts,
win 是 %WINDIR%\system32\drivers\etc\hosts
DNS 服务器负责解析域名,基于 C/S 架构,端口:53/udp、53/tcp。
实现 DNS 服务需要的软件之一是 bind。
- 全称域名 = 主机名 + 域名,比如 www 就是主机名
访问域名的时候是从下到上解析的。
根域往往不显示,实际上是 .

wanwang.aliyun.com这个网站可以看注册和出售的域名
域名也是有汉字的,但是用的少。域名上服务器一般要备案的。目前 DNS 是支持 IPv6 的。
递归查询和迭代查询在计网说了,省略部分:
上级 DNS 服务器记录下级 DNS 服务器的地址,没有下级域的就记录主机的地址。
由此来看 DNS 服务器应当是很多的,但是大部分都是部署在网络上的。
分布式:不完全集中、不完全分散。
- 存放查询目标的 DNS 服务器称为权威 DNS 服务器
- 访问的第一个 DNS 来查询就是递归,用户来逐层查就是迭代
查询过程:

- 缓存只有 win 有,cmd 输入
ipconfig/displaydns,ipconfig/flushdns可以清除缓存,
但是有些记录默认会再次加载的,比如 etc/hosts 文件里的缓存
- Linux 客户端默认是无缓存的
二、DNS 服务基本功能的实现
1. 云服务的 DNS 配置
购买的云服务就会有图形化界面配置 DNS,比自己手动方便,比如这样的:

有时候用户输错了域名依然可以访问,说明网站配置了通配符或者正则表达式:

很多时候不敲 www 也可以访问,有的是浏览器自动补全的,有的是 DNS 自动补全, 有的根本访问不了。需要在解析配置 @,如上图所示。
2. 企业内部的 DNS 配置(重要)
安装服务:

安装 bind 软件:
yum -y install bind bind-utils # 安装服务端,一般会自动安装相关库
yum -y install bind-utils # 安装客户端
补充一点:rpm 是底层工具,手动装单个 .rpm 文件、不自动解决依赖; yum 是上层工具(CentOS 7),自动解决依赖、从仓库安装; dnf 是 CentOS 8+ 的,算 yum 的升级版,语法更现代。
rpm -qi bind查看服务端版本(查的是已安装软件包的元信息)rpm -ql bind列出包安装了哪些文件,可以看到 DNS 服务的名称就是 namedyum info bind列出库中的版本(未下载)
ss -tuln 里那几个参数:
| 参数 | 全称 | 作用 |
|---|---|---|
-t | TCP | 只显示 TCP 端口 |
-u | UDP | 只显示 UDP 端口 |
-l | Listening | 只显示正在监听的端口(不显示已建立的连接) |
-n | Numeric | 不解析服务名(直接显示端口号,不把 80 显示成 http) |
验证端口:
ss -tuln 查看 DNS 的 TCP/53 和 UDP/53 端口是否打开。
systemctl enable --now named 开机自启服务,--now 的意思是立即启动,无需再 systemctl start。
有些服务需要修改配置文件后端口才会开放,有些服务只需要启动就能开放端口。
查看端口发现除了两个 53(对外主要提供服务),还有个 tcp/53, 这个是之前查看软件的文件中的 /usr/sbin/rndc 软件,用 rndc 管理 DNS 就会用到端口。
验证是否成功对外提供服务:
当我们 ping 的时候,或者通过网站访问域名的时候,主机找到的第一个 DNS 服务器就是 /etc/resolv.conf,如果是小型网络,里面写的就是网关了。
对于我们已经安装了 DNS 服务,本机就能解析,没必要去服务器查,但是做到这样需要手动配置, 直接把 DNS 文件(即修改网卡配置文件)的地址改成回环地址就可以了: /etc/sysconfig/network-scripts/ifcfg-ens33
| 地址 | 走哪条路 | 速度 | 用途 |
|---|---|---|---|
127.0.0.1 | 回环接口(不经过网卡) | 极快 | 本机服务自己查自己 |
192.168.88.128 | 物理网卡(经过网络栈) | 稍慢 | 其他机器来查询 |
- 修改 DNS 配置时优先修改 DNS1,DNS2 是备用的,测试环境可以只保留 DNS1
- 补充:ubuntu 网卡配置
sudo vi /etc/netplan/00-installer-config.yaml
修改配置文件如果还是不生效的,要 nmcli connection reload 重新加载网卡配置文件, 然后再去 up 一下 nmcli connection up ens33,或者重启 systemctl restart network 服务。
| 命令 | 作用 |
|---|---|
nmcli device status | 查看网卡状态 |
nmcli connection show | 查看所有连接配置 |
nmcli connection reload | 重新加载配置文件 |
nmcli connection down ens33 | 断开网卡 |
nmcli connection up ens33 | 启动网卡 |
- 特别注意,使用回环地址作为 DNS 解析域名,
/etc/hosts文件的主机映射不能有回环地址,
因为此文件的优先级高于网卡配置文件的
- 最后测试 ping 通 baidu 就是成功了
背后的工作原理,和 DNS 递归查询很像,装载 DNS 服务的主机充当了递归查询中负责询问其他 DNS 服务器的那个服务器,如图:

- 本机既是客户端,也是服务器
好处:本地有了缓存,下次访问直接解析(只缓存服务器)。
平时 win 用来上网的 DNS 服务器就是只缓存服务器,上面没有数据库,只缓存。
- 如何知道根服务器?任何符合 DNS 规范的软件天生都知道根是谁
- 比如
rpm -ql bind里面的/var/named/named.ca包含了 13 个根服务器存放的位置,
打开文件,里面的 A 记录就是 v4 地址,AAAA 记录是 v6, 当然是非常多的服务器共享一个 IP(虚拟 IP)负责解析域名(集群)
- **如果想要公司内部的主机都通过搭建的 DNS 来上网,就需要把需要上网的主机的网卡配置文件
改为充当 DNS 服务器的主机的内网 IP,然后重启网卡、重新加载网卡配置文件**
排错
如果只是上述操作还是不够的,内网主机还是无法通过内部 DNS 服务器上网 (结果就是客户端 ping 一个 IP 是通的,ping 一个域名就不行,这就说明 DNS 解析出了问题)。
直接 ping DNS 的 IP,通了,说明主机和 DNS 通信不是问题。
在 DNS 服务器抓包:tcpdump -i ens33 udp port 53 -nn
| 命令 | 作用 |
|---|---|
tcpdump -i ens33 udp port 53 | 抓 ens33 网卡的 DNS(UDP 53)流量 |
tcpdump -i ens33 tcp port 53 | 抓 DNS over TCP(大响应时用) |
tcpdump -i ens33 port 53 | 抓 UDP 和 TCP 的 53 端口 |
tcpdump -i ens33 -n udp port 53 | -n 不解析域名(显示 IP) |
tcpdump -i ens33 -nn udp port 53 | -nn 不解析域名 + 不解析端口 |
在最后加 -nn 代表纯数字化。
客户端 ping 一下,如果看到服务器有流量经过,证明只有请求,没有响应:

iptables -vnL | grep 53 查看防火墙规则,看是否是防火墙阻止了 DNS 服务接收远程请求。
| 部分 | 含义 |
|---|---|
iptables | Linux 防火墙命令 |
-v | verbose,显示详细信息(如包数量、字节数) |
-n | numeric,不解析 IP 和端口(直接显示数字,更快) |
-L | list,列出规则 |
| 大小写 | -L 是大写 L |
发现没有防火墙阻隔,ss -tunl 查看服务端口情况,发现 53 端口正常打开。
客户端 telnet 服务器IP 53 测试 53 端口能不能连,然后看到了报错,拒绝连接。
看到 53 端口是绑定在回环 IP,也就是只能访问该 IP 的端口(我们要给别的主机提供服务, 而不是只给自己提供解析服务),所以需要更改配置文件。
补充:暂时不用关 IPv6 的。
DNS 最主要的配置文件就是 /etc/named.conf,这是 C 语言风格的,结尾都是 ;。
其中 options 选项,logging 日志相关,第三块是数据库相关,重点在 options。
其中直接看到了 127.0.0.1,直接在后面补服务器 IP,记得加分号(如图)即可 (服务器 IP 一定要是固定的,就需要修改另外的配置文件了)。

改完了要检查语法,没有错误,然后再重启服务,减少服务挂掉的可能, DNS 服务中有个检查语法的指令 named-checkconf,如果语法错误就会输出内容。
restart 服务,然后检查端口,看到修改后的如图:

客户端再次 ping,还失败了。
直接在配置文件添加服务器 IP 的操作其实并不是最优的,因为服务器 IP 可能会变化, 可能会忘掉 DNS 配置文件的,所以可以像修改云服务的防火墙规则流量一样, 写 0.0.0.0 是不支持的,可能其他服务会允许比如 Apache, 可以写 DNS 服务自带的关键字指代所有 IP:localhost,表示当前主机的 IP。
我们再回到解析不通的问题,如果把服务器的 DNS 解析指向自己(修改网卡配置文件),ping 是通的 (注意这里不写回环,要写内网服务器 IP,是为了测试这个 IP)。
然后看看是不是 DNS 配置文件里对此有单独的设置,找到字段 allow-query, 这玩意一看就知道神马意思,后面是 localhost;,只允许本机查询,后面直接加允许的 IP。
保存,检查语法,重启(如果觉得 reload/restart 太长了,写 rndc reload)。

但是按照上述方法 IP 改变了也得一个个配,这么麻烦吗?当然没有,可以这样:
不写 IP,写 CIDR,比如 10.0.0.0/24 和 192.168.88.0/24,可以写多个网段, 假设对外提供公共解析服务直接写 any 即可,是 DNS 内置的关键字。
到此位置,配置完成了 DNS 服务。
还有一种最简单的写法,直接注释掉刚才需要修改的两个字段所在行, 这样默认就是 localhost 和 any 的设置(一般不会这样的)。
当前搭建的服务只具备上网功能,并不具备完整 DNS 服务器的功能, 比如服务器只是递归查询,而不是自己解析(不是权威 DNS 服务器),同时也具有缓存。
如何知道有缓存功能呢?
把服务器的网络掐了,看刚才客户端 ping 的域名还能不能通了,但是这边有点特殊, 如果掐了网,缓存也会被删除的,比如下面的步骤。
掐断指定主机网络直接断掉路由即可。
route -n 显示和操作网络路由表。
ip route 查看路由。
路由通常是 default via IP。
ip route del [路由]
比如 default via 192.168.88.2
- 掐了之后再 ping,按理来说是有缓存能查到的,但是刚才提到了,没网络会删缓存,所以这里是不通的
dig 是一个 DNS 测试查询工具,可以 dig 域名 查看该域名的缓存, 比如没断网之前 ping 了 www.taobao.com 然后可以 dig 看记录,但是断网了 dig 就看不到记录了,如图所示:

rndc --help 可以查看指令帮助。
ip route add [路由]加回路由就能恢复网络了route -n看到了路由就是成功了
添加新的路由要删除旧的路由哦。
- 如果想看 DNS 转发查询的过程可以让服务器抓包 udp/53,然后客户端 ping 一下
- 如果只有两条请求,没有到互联网的,比如下图,就是缓存查询

- 如果有很多那就是递归查询了
这个问题不必深究。
rndc flush 清除缓存。
以上就实现了 DNS 缓存服务器的搭建,实际上我们需要的是能够查询企业内部名称解析服务的 DNS 服务器。
这一页折腾下来,套路基本就固定了:yum install -y bind bind-utils 装, 改 /etc/named.conf 里的 listen-on(补内网 IP)和 allow-query(补内网网段或者 any), named-checkconf 查语法,systemctl enable --now named 起来, 防火墙 firewall-cmd --add-service=dns --permanent,客户端网卡把 DNS1 指过来, 最后 ping baidu.com、tcpdump -i ens33 udp port 53 -nn 验证。 想看缓存就把路由删了掐网,应该解析不了,rndc flush 清一下缓存就更是啥都没有了。