强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Dnsmasq 服务搭建完全教程 / 第 03 章:DNS 配置

第 03 章:DNS 配置

3.1 DNS 基础概念

3.1.1 DNS 查询类型

Dnsmasq 支持多种 DNS 记录类型:

记录类型说明示例
AIPv4 地址example.com → 93.184.216.34
AAAAIPv6 地址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
家庭网络< 20150-500
小型办公20-100500-2000
中型网络100-5002000-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-recordaddress 更灵活,支持同时配置 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 小结

功能关键配置项说明
上游 DNSserver=IP + no-resolv指定上游,禁用 resolv.conf
按域名转发server=/域/DNS不同域名用不同 DNS
缓存cache-size=N缓存条目数量
本地域名domain= + expand-hosts自动附加域名后缀
自定义记录address=/域名/IPA/AAAA 记录
hosts 文件addn-hosts=文件批量添加记录
安全dnssecbogus-privDNSSEC 和反劫持

3.11 扩展阅读