目录

一、引言:为什么需要DNS?

二、/etc/hosts:DNS出现之前的解决方案

2.1 hosts文件的工作原理

2.2 hosts文件的局限性

三、Dnsmasq:最轻量的DNS服务器

3.1 什么是Dnsmasq?

3.2 安装与启动

3.3 配置自定义域名解析

3.4 验证自定义域名解析

四、BIND9简介:企业级的DNS方案

五、实战:用DNS劫持广告域名

5.1 原理

5.2 配置Dnsmasq广告屏蔽

5.3 使用社区维护的广告域名列表

六、故障排查清单

6.1 DNS配置排查命令

6.2 常见问题速查

七、本篇小结

动手练习

八、下篇预告


一、引言:为什么需要DNS?

假如没有DNS,你访问百度不是输入baidu.com,而是输入110.242.68.66。你能记住几个这样的IP地址?

DNS(Domain Name System)就是为解决这个问题而生的——它把人类容易记忆的域名,翻译成计算机需要的IP地址。

但DNS的作用远不止“翻译”。在运维工作中,自己搭建DNS服务器有两个非常实用的场景:

  1. 内网域名解析:公司内部的服务(如GitLab、Jenkins、Nexus)都在内网,没有公网DNS记录。自己搭一个DNS,员工就能用gitlab.internal这样的域名访问,不用记IP

  2. 广告过滤:把所有广告域名的解析结果指向一个不存在的地址,广告自然就加载不出来了——这是网络级别的广告屏蔽,不用装任何浏览器插件

二、/etc/hosts:DNS出现之前的解决方案

2.1 hosts文件的工作原理

在DNS出现之前,互联网上的每一台计算机都用一个文件来记录“域名→IP”的映射关系——这就是/etc/hosts

bash

cat /etc/hosts

输出(典型的Linux hosts文件):

text

127.0.0.1    localhost
127.0.1.1    myhostname

# 你可以手动添加自定义映射
192.168.1.100   gitlab.internal
192.168.1.101   jenkins.internal

当你访问gitlab.internal时,系统会先查hosts文件,如果找到了对应的IP,就直接使用,不会再发起DNS查询。

优先级:现代Linux系统默认先查hosts文件,再查DNS服务器。这个顺序由/etc/nsswitch.conf中的hosts: files dns控制——files代表hosts文件,dns代表DNS服务器查询,排在前面优先级更高。

2.2 hosts文件的局限性

局限说明
单机生效每台机器都得单独维护,机器多了根本无法同步
静态配置IP变了就得手动改,DHCP动态分配IP的场景根本没法用
无高级功能不支持泛域名解析(*.internal)、不支持负载均衡、不支持故障转移
无法应付大规模互联网有上亿个域名,一个hosts文件不可能装下

当你管理三台以上的服务器时,hosts文件就会变成噩梦——每加一台新机器,你都得在所有机器上更新hosts。这时候就需要一个集中式的DNS服务器了。

三、Dnsmasq:最轻量的DNS服务器

3.1 什么是Dnsmasq?

Dnsmasq是一个轻量级的DNS和DHCP服务器,专为小型网络设计。它的特点:

  • 配置极简:核心配置往往只需要几行

  • 资源占用极低:几十MB内存就能跑,树莓派上也能流畅运行

  • 自动读取/etc/hosts:你只需要把内网域名写进服务器的hosts文件,Dnsmasq就能把它们作为DNS记录对外提供

  • 支持DNS缓存:加速重复查询,减轻上游DNS负担

对于几十台到几百台规模的内网环境,Dnsmasq是性价比最高的选择。

3.2 安装与启动

bash

# Ubuntu/Debian
sudo apt update && sudo apt install dnsmasq -y

# CentOS/RHEL
sudo dnf install dnsmasq -y

# 启动并设为开机自启
sudo systemctl start dnsmasq
sudo systemctl enable dnsmasq

Dnsmasq默认监听53端口(DNS标准端口)。Ubuntu/Debian系统可能自带systemd-resolved,它也占用53端口,会导致Dnsmasq启动失败。排查方法:

bash

# 查看53端口被谁占用
sudo ss -tulnp | grep :53

# 如果systemd-resolved占用了53端口,停止它并禁用
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved

# 处理/etc/resolv.conf软链接(避免被systemd-resolved覆盖)
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf

3.3 配置自定义域名解析

Dnsmasq的默认配置非常精简,大部分功能都需要手动配置。编辑配置文件:

bash

sudo vim /etc/dnsmasq.conf

在文件末尾追加以下内容:

ini

# 监听所有网络接口(生产环境建议指定具体IP,如 interface=eth0)
interface=*

# 上游DNS服务器(Dnsmasq自己解析不了的域名,转发给Google和Cloudflare的DNS)
server=8.8.8.8
server=8.8.4.4

# 监听地址(绑定的内网IP,根据你的服务器IP修改)
listen-address=192.168.1.100

# 禁止读取 /etc/resolv.conf 获取上游DNS(我们用 server= 手动指定)
no-resolv

# DNS缓存大小(缓存1000条查询结果,加快重复访问速度)
cache-size=1000

然后配置内网自定义域名:

bash

# 方法一:直接写入服务器的 /etc/hosts
echo "192.168.1.10  gitlab.internal" | sudo tee -a /etc/hosts
echo "192.168.1.20  jenkins.internal" | sudo tee -a /etc/hosts
echo "192.168.1.30  nexus.internal" | sudo tee -a /etc/hosts

bash

# 方法二:通过Dnsmasq的专用配置文件(更规范)
sudo mkdir -p /etc/dnsmasq.d
sudo vim /etc/dnsmasq.d/internal.conf

添加内容:

text

# 内网自定义域名
address=/gitlab.internal/192.168.1.10
address=/jenkins.internal/192.168.1.20
address=/nexus.internal/192.168.1.30

# 泛域名解析(所有 .app.internal 都解析到这个IP)
address=/.app.internal/192.168.1.50

重启Dnsmasq:

bash

sudo systemctl restart dnsmasq

3.4 验证自定义域名解析

在DNS服务器本机测试:

bash

# 测试自定义域名(@127.0.0.1 指定用本机的DNS服务查询)
nslookup gitlab.internal 127.0.0.1

# 或者用dig
dig @127.0.0.1 gitlab.internal

在其他内网机器上测试(将它们的DNS设置为你的Dnsmasq服务器IP):

bash

# Linux:临时修改DNS
echo "nameserver 192.168.1.100" | sudo tee /etc/resolv.conf

# 测试
ping gitlab.internal
nslookup jenkins.internal

Windows上修改DNS:控制面板 → 网络和共享中心 → 更改适配器设置 → 右键网卡属性 → IPv4属性 → DNS服务器填192.168.1.100

四、BIND9简介:企业级的DNS方案

Dnsmasq适合小型内网,但如果需要更复杂的功能——比如多区域管理、主从DNS同步、动态更新——就需要BIND9

BIND(Berkeley Internet Name Domain)是互联网上使用最广泛的DNS服务器软件,大部分公网DNS服务器都在运行BIND。它功能强大但配置复杂得多,这里只做简要对比:

对比维度DnsmasqBIND9
适用规模几十~几百台几百~几万台以上
配置复杂度★☆☆☆☆★★★★☆
内存占用~50MB~200MB+
区域传输不支持支持主从同步
学习成本10分钟上手需要系统学习DNS协议

如果你的环境和需求符合以下条件之一,可以考虑学习BIND9:

  • 需要管理多个DNS区域(zone)

  • 需要部署主从DNS服务器实现高可用

  • 需要支持DDNS(动态DNS更新)

  • 对DNS协议有深入学习的兴趣

五、实战:用DNS劫持广告域名

这是本篇最有趣的部分——利用DNS实现网络级别的广告屏蔽

5.1 原理

广告加载的流程通常是:网页 → 请求ads.example.com/some_ad.js → DNS查询 → 获取广告服务器IP → 加载广告。

如果在DNS层面,把ads.example.com解析到127.0.0.1(或者0.0.0.0),浏览器就无法加载广告内容——因为广告请求全被“黑洞”了。

5.2 配置Dnsmasq广告屏蔽

bash

sudo vim /etc/dnsmasq.d/adblock.conf

添加以下内容:

text

# 把所有常见广告域名指向 0.0.0.0(指向自己或空地址,浏览器发起请求后立即失败)
address=/doubleclick.net/0.0.0.0
address=/googleadservices.com/0.0.0.0
address=/googlesyndication.com/0.0.0.0
address=/adservice.google.com/0.0.0.0

# 一些常见的第三方广告域名
address=/ads.example.com/0.0.0.0
address=/tracker.analytics.com/0.0.0.0

效果验证:重启Dnsmasq后,在本机试试:

bash

# 解析广告域名(应该返回 0.0.0.0)
nslookup doubleclick.net 127.0.0.1

# ping 测试
ping ads.example.com    # 输出 "PING ads.example.com (0.0.0.0)" 说明劫持成功

5.3 使用社区维护的广告域名列表

手动维护广告域名费时费力,社区已经有现成的列表可用:

bash

# 下载一个经过整理的hosts广告屏蔽列表,转换为Dnsmasq格式
curl -s https://someonewhocares.org/hosts/zero/hosts | \
    grep '^0\.0\.0\.0' | \
    awk '{print "address=/"$2"/0.0.0.0"}' | \
    sudo tee /etc/dnsmasq.d/adblock_community.conf

# 重启Dnsmasq
sudo systemctl restart dnsmasq

注意:社区列表可能包含数千甚至上万条域名,Dnsmasq的处理性能在普通服务器上完全够用。但建议只选择你信任的列表来源,避免误拦截正常网站。

六、故障排查清单

6.1 DNS配置排查命令

bash

# 查看当前系统DNS配置
cat /etc/resolv.conf

# 检查53端口是否被占用
sudo ss -tulnp | grep :53

# 查看Dnsmasq日志(排查配置错误)
sudo journalctl -u dnsmasq -f

# 测试DNS解析(逐步定位)
nslookup baidu.com                    # 用系统默认DNS
nslookup baidu.com 127.0.0.1          # 用本机DNS
nslookup gitlab.internal 192.168.1.100  # 用内网DNS

6.2 常见问题速查

问题现象可能原因解决方案
Dnsmasq无法启动53端口被占用(通常是systemd-resolved)sudo ss -tulnp | grep :53,停掉占用进程
内网域名解析不到其他机器的DNS没指向Dnsmasq检查/etc/resolv.conf(Linux)或网卡DNS设置(Windows)
某些网站打不开广告列表误伤了正常网站检查/etc/dnsmasq.d/下的屏蔽列表,注释掉怀疑的域名后重启Dnsmasq
解析变慢上游DNS延迟高或cache-size太小检查server=上游DNS配置,增大cache-size

七、本篇小结

DNS层次

text

/etc/hosts(单机)→ Dnsmasq(小型内网DNS)→ BIND9(企业级DNS)

Dnsmasq核心配置

配置项作用示例
server=IP指定上游DNSserver=8.8.8.8
address=/域名/IP自定义域名解析address=/gitlab.internal/192.168.1.10
address=/域名/0.0.0.0屏蔽域名(广告过滤的核心)address=/ads.com/0.0.0.0
cache-size=NDNS缓存条数cache-size=1000

DNS劫持广告的原理:把广告域名的DNS指向127.0.0.10.0.0.0,浏览器就无法加载广告内容——无需插件,网络级别生效。

动手练习

bash

# 1. 确认Dnsmasq安装并运行
sudo apt install dnsmasq -y
sudo systemctl status dnsmasq

# 2. 添加一个自定义域名并测试
sudo mkdir -p /etc/dnsmasq.d
echo "address=/myapp.internal/192.168.1.100" | sudo tee /etc/dnsmasq.d/myapp.conf
sudo systemctl restart dnsmasq
nslookup myapp.internal 127.0.0.1

# 3. 劫持一个常见广告域名体验DNS屏蔽效果
echo "address=/doubleclick.net/0.0.0.0" | sudo tee /etc/dnsmasq.d/adtest.conf
sudo systemctl restart dnsmasq
nslookup doubleclick.net 127.0.0.1

八、下篇预告

DNS把域名解析为IP,但一个域名往往只对应一个IP。如果这台服务器挂了怎么办?如果流量太大一台服务器撑不住怎么办?

下一篇我们将学习NFS网络文件系统——它是分布式存储的基础,让多台服务器共享同一份文件数据。你将理解“无状态协议”的设计哲学,以及为什么NFS会让进程进入我们第11篇学过的“D状态”不可中断睡眠。


延伸思考:DNS虽然解决了集中式域名解析的问题,但/etc/hosts并没有消失——你可以在服务器上把127.0.0.1 localhost这一行删掉,看看会发生什么?很多服务的本地通信都会依赖localhost解析。这就是为什么hosts文件在单机配置中依然重要:它是绕过DNS最快、最可靠的解析方式。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐