目录
[2.1 hosts文件的工作原理](#2.1 hosts文件的工作原理)
[2.2 hosts文件的局限性](#2.2 hosts文件的局限性)
[3.1 什么是Dnsmasq?](#3.1 什么是Dnsmasq?)
[3.2 安装与启动](#3.2 安装与启动)
[3.3 配置自定义域名解析](#3.3 配置自定义域名解析)
[3.4 验证自定义域名解析](#3.4 验证自定义域名解析)
[5.1 原理](#5.1 原理)
[5.2 配置Dnsmasq广告屏蔽](#5.2 配置Dnsmasq广告屏蔽)
[5.3 使用社区维护的广告域名列表](#5.3 使用社区维护的广告域名列表)
[6.1 DNS配置排查命令](#6.1 DNS配置排查命令)
[6.2 常见问题速查](#6.2 常见问题速查)
一、引言:为什么需要DNS?
假如没有DNS,你访问百度不是输入baidu.com,而是输入110.242.68.66。你能记住几个这样的IP地址?
DNS(Domain Name System)就是为解决这个问题而生的------它把人类容易记忆的域名,翻译成计算机需要的IP地址。
但DNS的作用远不止"翻译"。在运维工作中,自己搭建DNS服务器有两个非常实用的场景:
-
内网域名解析 :公司内部的服务(如GitLab、Jenkins、Nexus)都在内网,没有公网DNS记录。自己搭一个DNS,员工就能用
gitlab.internal这样的域名访问,不用记IP -
广告过滤 :把所有广告域名的解析结果指向一个不存在的地址,广告自然就加载不出来了------这是网络级别的广告屏蔽,不用装任何浏览器插件
二、/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。它功能强大但配置复杂得多,这里只做简要对比:
| 对比维度 | Dnsmasq | BIND9 |
|---|---|---|
| 适用规模 | 几十~几百台 | 几百~几万台以上 |
| 配置复杂度 | ★☆☆☆☆ | ★★★★☆ |
| 内存占用 | ~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 |
| 内网域名解析不到 | 其他机器的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 |
指定上游DNS | server=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=N |
DNS缓存条数 | cache-size=1000 |
DNS劫持广告的原理 :把广告域名的DNS指向127.0.0.1或0.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最快、最可靠的解析方式。