首页  /  DNS 服务  /  正文

DNS 工作原理与基本功能实现

DNS 服务 2026-10-01📖 12 分钟👁 —
🔧 运维进阶 · 常用服务搭建第 4 / 8 页12345678📖 完整导航 →

一、DNS 工作原理

win 是 %WINDIR%\system32\drivers\etc\hosts

DNS 服务器负责解析域名,基于 C/S 架构,端口:53/udp、53/tcp。

实现 DNS 服务需要的软件之一是 bind。

访问域名的时候是从下到上解析的。

根域往往不显示,实际上是 .

根域往下逐层的域名结构

域名也是有汉字的,但是用的少。域名上服务器一般要备案的。目前 DNS 是支持 IPv6 的。

递归查询和迭代查询在计网说了,省略部分:

上级 DNS 服务器记录下级 DNS 服务器的地址,没有下级域的就记录主机的地址。

由此来看 DNS 服务器应当是很多的,但是大部分都是部署在网络上的。

分布式:不完全集中、不完全分散。

查询过程:

查询过程的链路,hosts 文件 → 本地缓存 → DNS 服务器 → 迭代查询

但是有些记录默认会再次加载的,比如 etc/hosts 文件里的缓存


二、DNS 服务基本功能的实现

1. 云服务的 DNS 配置

购买的云服务就会有图形化界面配置 DNS,比自己手动方便,比如这样的:

阿里云云解析里添加一条 A 记录

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

解析记录列表里红框圈出的 * 泛解析

很多时候不敲 www 也可以访问,有的是浏览器自动补全的,有的是 DNS 自动补全, 有的根本访问不了。需要在解析配置 @,如上图所示。

2. 企业内部的 DNS 配置(重要)

安装服务:

yum list all bind* 里几个包分别是干什么的

安装 bind 软件:

yum -y install bind bind-utils    # 安装服务端,一般会自动安装相关库
yum -y install bind-utils         # 安装客户端

补充一点:rpm 是底层工具,手动装单个 .rpm 文件、不自动解决依赖; yum 是上层工具(CentOS 7),自动解决依赖、从仓库安装; dnf 是 CentOS 8+ 的,算 yum 的升级版,语法更现代。

ss -tuln 里那几个参数:

参数全称作用
-tTCP只显示 TCP 端口
-uUDP只显示 UDP 端口
-lListening只显示正在监听的端口(不显示已建立的连接)
-nNumeric不解析服务名(直接显示端口号,不把 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物理网卡(经过网络栈)稍慢其他机器来查询

修改配置文件如果还是不生效的,要 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 递归查询很像,装载 DNS 服务的主机充当了递归查询中负责询问其他 DNS 服务器的那个服务器,如图:

DNS 服务主机充当递归查询里负责问别人的那个服务器

好处:本地有了缓存,下次访问直接解析(只缓存服务器)。

平时 win 用来上网的 DNS 服务器就是只缓存服务器,上面没有数据库,只缓存。

打开文件,里面的 A 记录就是 v4 地址,AAAA 记录是 v6, 当然是非常多的服务器共享一个 IP(虚拟 IP)负责解析域名(集群)

改为充当 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 一下,如果看到服务器有流量经过,证明只有请求,没有响应:

tcpdump 里只看到请求,没有响应

iptables -vnL | grep 53 查看防火墙规则,看是否是防火墙阻止了 DNS 服务接收远程请求。

部分含义
iptablesLinux 防火墙命令
-vverbose,显示详细信息(如包数量、字节数)
-nnumeric,不解析 IP 和端口(直接显示数字,更快)
-Llist,列出规则
大小写-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 一定要是固定的,就需要修改另外的配置文件了)。

options 里 listen-on 补上服务器 IP

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

restart 服务,然后检查端口,看到修改后的如图:

53 端口已经绑到了服务器 IP 上

客户端再次 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)。

rndc reload 就等于 systemctl reload named

但是按照上述方法 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。

比如 default via 192.168.88.2

dig 是一个 DNS 测试查询工具,可以 dig 域名 查看该域名的缓存, 比如没断网之前 ping 了 www.taobao.com 然后可以 dig 看记录,但是断网了 dig 就看不到记录了,如图所示:

断网之后 dig 看不到记录,这里是空的

rndc --help 可以查看指令帮助。

添加新的路由要删除旧的路由哦。

抓包里只有一问一答两条记录,说明走的是缓存

这个问题不必深究。

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 清一下缓存就更是啥都没有了。