Dnsmasq 服务搭建完全教程 / 第 03 章:DNS 配置
第 03 章:DNS 配置
3.1 DNS 基础概念
3.1.1 DNS 查询类型
Dnsmasq 支持多种 DNS 记录类型:
| 记录类型 | 说明 | 示例 |
|---|---|---|
| A | IPv4 地址 | example.com → 93.184.216.34 |
| AAAA | IPv6 地址 | example.com → 2606:2800:220:1:... |
| CNAME | 别名 | www.example.com → example.com |
| MX | 邮件交换 | example.com → mail.example.com (pri=10) |
| TXT | 文本记录 | example.com → "v=spf1 ..." |
| SRV | 服务记录 | _sip._tcp.example.com → sip.example.com:5060 |
| PTR | 反向解析 | 34.216.184.93 → example.com |
| NS | 域名服务器 | example.com → ns1.example.com |
| SOA | 权威记录 | 区域起始授权 |
3.1.2 DNS 查询流程
客户端 Dnsmasq 上游 DNS
│ │ │
│── 查询 example.com ──→ │ │
│ ├── 查本地记录 │
│ ├── 查缓存 │
│ │ (未命中) │
│ ├── 转发查询 ─────────────→ │
│ │ ←── 响应 ─────────────────┤
│ ├── 缓存响应 │
│←── 返回结果 ───────────┤ │
3.2 上游 DNS 配置
3.2.1 指定上游 DNS 服务器
# /etc/dnsmasq.d/01-upstream.conf
# 使用国内公共 DNS
server=223.5.5.5 # 阿里 DNS
server=119.29.29.29 # 腾讯 DNS
server=114.114.114.114 # 114 DNS
# 使用国际公共 DNS
server=8.8.8.8 # Google DNS
server=8.8.4.4 # Google DNS 备用
server=1.1.1.1 # Cloudflare DNS
# 指定非标准端口的 DNS
server=192.168.1.253#5353
# 通过 DoH (DNS over HTTPS) 查询
# 需要编译时支持或配合 stubby/cloudflared
# 不读取 /etc/resolv.conf(重要!否则会重复解析)
no-resolv
# 不轮询上游服务器(只在首个可用时使用)
no-poll
警告:
no-resolv选项阻止 Dnsmasq 读取/etc/resolv.conf。如果不设置no-resolv,Dnsmasq 会把/etc/resolv.conf中的 nameserver 也作为上游,可能导致循环解析。
3.2.2 按域名选择上游 DNS
将不同域名的查询发送到不同的上游 DNS 服务器:
# 企业内网域名走内部 DNS
server=/corp.example.com/10.0.0.53
server=/internal.lan/10.0.0.53
# 特定域名走指定 DNS(例如需要通过特定 DNS 解锁)
server=/netflix.com/1.1.1.1
server=/openai.com/8.8.8.8
# 使用 # 号指定端口
server=/special.example.com/192.168.100.1#5353
# 其他域名走默认上游
server=223.5.5.5
server=8.8.8.8
no-resolv
业务场景:企业网络中,内部域名(.corp、.internal)必须通过内网 DNS 解析才能访问内部系统,而外部域名通过公网 DNS 解析。
3.2.3 上游 DNS 服务器选择策略
# 严格顺序(按配置顺序尝试)
strict-order
# 所有服务器并行查询,使用最快响应
# (Dnsmasq 默认行为)
# 只使用第一个响应的服务器
all-servers
3.3 DNS 缓存配置
3.3.1 基本缓存设置
# /etc/dnsmasq.d/02-cache.conf
# 缓存条目数量(0 表示禁用缓存)
cache-size=1000
# 缓存最小 TTL(秒),防止过短的缓存时间
min-cache-ttl=300
# 负向缓存 TTL(解析失败的结果也缓存)
neg-ttl=60
# 本地域名的缓存 TTL
local-ttl=300
3.3.2 缓存大小估算
缓存大小应根据网络规模和设备数量调整:
| 网络规模 | 设备数 | 推荐 cache-size |
|---|---|---|
| 家庭网络 | < 20 | 150-500 |
| 小型办公 | 20-100 | 500-2000 |
| 中型网络 | 100-500 | 2000-5000 |
| 大型网络 | 500+ | 5000-10000 |
注意:每个缓存条目约占用 70-100 字节内存。1000 条缓存约需 100 KB 内存。
3.3.3 查看缓存统计
# 发送 SIGUSR1 信号输出统计信息
sudo kill -USR1 $(pidof dnsmasq)
# 查看日志中的统计
sudo journalctl -u dnsmasq --since "1 min ago" | grep -i cache
# 输出示例:
# dnsmasq[1234]: cache size 1000, 0/653 cache insertions re-used unexpired cache entries.
# dnsmasq[1234]: queries forwarded 423, queries answered locally 230
3.3.4 清除缓存
# 方法 1:重载配置(清除缓存)
sudo systemctl reload dnsmasq
# 方法 2:发送 SIGHUP
sudo kill -HUP $(pidof dnsmasq)
# 方法 3:重启服务
sudo systemctl restart dnsmasq
3.4 本地域名配置
3.4.1 设置本地域名
# /etc/dnsmasq.d/03-localdomain.conf
# 本地域名后缀
domain=home.lan
# 将 hosts 文件中的短名称自动附加域名
# 例如 hosts 中有 "192.168.1.10 nas",则 nas → nas.home.lan
expand-hosts
# 将 home.lan 的查询限定在本地解析,不转发
local=/home.lan/
# 同理,局域网反向查询也限定本地
local=/168.192.in-addr.arpa/
3.4.2 自定义 A 记录
# /etc/dnsmasq.d/04-custom-records.conf
# A 记录:域名 → IPv4
address=/nas.home.lan/192.168.1.10
address=/printer.home.lan/192.168.1.20
address=/camera1.home.lan/192.168.1.30
# AAAA 记录:域名 → IPv6
address=/nas.home.lan/fd00::10
# 泛域名解析(所有子域名指向同一 IP)
address=/dev.example.com/127.0.0.1
# 这会解析 *.dev.example.com 全部指向 127.0.0.1
# 反向 PTR 记录
ptr-record=10.1.168.192.in-addr.arpa,"nas.home.lan"
3.4.3 host-record 高级配置
host-record 比 address 更灵活,支持同时配置 A 和 AAAA 记录:
# 同时添加 A 和 AAAA 记录
host-record=nas.home.lan,192.168.1.10,fd00::10
host-record=server.home.lan,192.168.1.5,fd00::5
# 带 TTL 的记录
host-record=static.home.lan,192.168.1.100,3600
3.4.4 MX 和 TXT 记录
# MX 记录(邮件)
mx-target=mail.example.com
mx-host=example.com,mail.example.com,10
# TXT 记录(SPF、验证等)
txt-record=example.com,"v=spf1 mx a ~all"
txt-record=_dmarc.example.com,"v=DMARC1; p=reject; rua=mailto:admin@example.com"
# SRV 记录(服务发现)
srv-host=_sip._tcp.example.com,sip.example.com,5060,10,0
srv-host=_xmpp-client._tcp.example.com,xmpp.example.com,5222,5,0
3.5 DNS 转发规则
3.5.1 基本转发配置
# 转发所有查询到上游 DNS
server=8.8.8.8
no-resolv
# 按域名转发到不同 DNS
server=/corp.example.com/10.0.0.53 # 企业内网
server=/home.arpa/192.168.1.1 # 本地
server=223.5.5.5 # 默认上游
no-resolv
3.5.2 禁止转发特定域名
# 本地域名不转发(直接返回 NXDOMAIN)
local=/test/
# 从上游结果中过滤特定域名
# 例如,不解析 example.com(返回无记录)
server=/example.com/#
# 完全屏蔽某个域名及其子域名
address=/ads.example.com/0.0.0.0
address=/ads.example.com/::
3.5.3 域名重写
# 将 old-domain.com 重写为 new-domain.com
cname=old-domain.com,new-domain.com
# 将本地域名指向另一个本地域名
cname=www.home.lan,webserver.home.lan
3.6 hosts 文件集成
3.6.1 Dnsmasq 的 hosts 查找顺序
1. --addn-hosts 指定的附加文件
2. /etc/hosts(默认读取)
3. DHCP 租约中的主机名
3.6.2 使用附加 hosts 文件
# /etc/dnsmasq.d/05-hosts.conf
# 使用自定义 hosts 文件(替代或补充 /etc/hosts)
addn-hosts=/etc/dnsmasq.hosts
# 可以指定多个文件
addn-hosts=/etc/dnsmasq.hosts,/etc/dnsmasq.extra-hosts
# /etc/dnsmasq.hosts
# 格式与 /etc/hosts 相同
192.168.1.10 nas nas.home.lan
192.168.1.11 webserver web.home.lan
192.168.1.12 dbserver db.home.lan
192.168.1.20 printer printer.home.lan
fd00::10 nas6 nas6.home.lan
注意:修改 hosts 文件后发送
SIGHUP即可热重载,无需重启 Dnsmasq。
3.7 DNS 安全配置
3.7.1 DNSSEC 支持
# /etc/dnsmasq.d/06-dnssec.conf
# 启用 DNSSEC 验证
dnssec
# 信任锚(根区域 KSK)
# Dnsmasq 2.80+ 通常内置,也可手动指定
dnssec-check-unsigned
# 信任的 DNSSEC 时间偏差容限(秒)
dnssec-timestamp=/var/lib/dnsmasq/dnssec-timestamp
注意:DNSSEC 可能增加查询延迟。如果上游 DNS 不支持 DNSSEC,建议禁用。
3.7.2 防止 DNS 劫持
# 强制使用指定的上游 DNS(忽略 /etc/resolv.conf)
no-resolv
# 禁止 Dnsmasq 轮询上游(避免被篡改的 resolv.conf 影响)
no-poll
# 过滤 Bogon IP(不应出现在公网的私有地址)
bogus-priv
3.8 高级 DNS 功能
3.8.1 DNS 重绑定保护
DNS 重绑定攻击可以绕过同源策略访问内网服务:
# 禁止返回私有 IP 地址的 DNS 结果(默认行为)
# 防止外部域名解析到 192.168.x.x、10.x.x.x 等
stop-dns-rebind
# 如果某些域名确实需要解析到内网 IP
rebind-localhost-ok
# 允许特定域名解析到私有地址
rebind-domain-ok=/myhost.example.com/
rebind-domain-ok=/internal.corp/
3.8.2 查询日志与分析
# /etc/dnsmasq.d/07-logging.conf
# 记录所有 DNS 查询
log-queries
# 日志输出到独立文件
log-facility=/var/log/dnsmasq/dnsmasq.log
# 额外记录 DHCP 事件
log-dhcp
# 实时查看查询日志
sudo tail -f /var/log/dnsmasq/dnsmasq.log
# 统计查询最多的域名
sudo awk '{print $6}' /var/log/dnsmasq/dnsmasq.log | \
sort | uniq -c | sort -rn | head -20
# 统计查询来源
sudo grep "query\[" /var/log/dnsmasq/dnsmasq.log | \
awk '{print $NF}' | sort | uniq -c | sort -rn | head -20
3.8.3 通配符域名
# 将 *.example.com 全部解析到 127.0.0.1
address=/example.com/127.0.0.1
# 等价于 example.com 及其所有子域名
# 将所有 .test 域名解析到 127.0.0.1(开发用)
address=/test/127.0.0.1
# 将所有 .local 域名解析到局域网
address=/local/192.168.1.1
3.9 完整 DNS 配置示例
# /etc/dnsmasq.d/00-dns-full.conf
# 完整的 DNS 配置示例
# === 基础设置 ===
listen-address=127.0.0.1,192.168.1.1
bind-interfaces
port=53
# === 本地域名 ===
domain=home.lan
expand-hosts
local=/home.lan/
# === 上游 DNS ===
server=223.5.5.5
server=119.29.29.29
server=8.8.8.8
no-resolv
strict-order
# === 缓存 ===
cache-size=1000
min-cache-ttl=300
neg-ttl=60
# === 自定义记录 ===
addn-hosts=/etc/dnsmasq.hosts
address=/printer.home.lan/192.168.1.20
address=/nas.home.lan/192.168.1.10
host-record=gateway.home.lan,192.168.1.1
# === 安全 ===
bogus-priv
stop-dns-rebind
rebind-localhost-ok
# === 日志 ===
log-queries
log-facility=/var/log/dnsmasq/dnsmasq.log
3.10 小结
| 功能 | 关键配置项 | 说明 |
|---|---|---|
| 上游 DNS | server=IP + no-resolv | 指定上游,禁用 resolv.conf |
| 按域名转发 | server=/域/DNS | 不同域名用不同 DNS |
| 缓存 | cache-size=N | 缓存条目数量 |
| 本地域名 | domain= + expand-hosts | 自动附加域名后缀 |
| 自定义记录 | address=/域名/IP | A/AAAA 记录 |
| hosts 文件 | addn-hosts=文件 | 批量添加记录 |
| 安全 | dnssec、bogus-priv | DNSSEC 和反劫持 |