dnsmasq 详解

dnsmasq 是一个轻量级的网络服务软件,它集成了 DNS 转发器 (DNS Forwarder)、DHCP 服务器 (DHCP Server) 和 TFTP 服务器 (TFTP Server) 功能。因其小巧、易用和高效的特点,dnsmasq 在家庭网络、小型办公室 (SOHO) 环境以及嵌入式设备(如路由器)中非常流行。

1. 什么是 dnsmasq?

简单来说,dnsmasq 可以被视为一个本地的 DNS 缓存服务器和 DHCP 服务器。

  • DNS 转发器:当你的设备需要解析一个域名时,它首先会向 dnsmasq 发送请求。如果 dnsmasq 已经缓存了这个域名的 IP 地址,它会立即返回;如果没有,它会将请求转发给上游的 DNS 服务器(例如你的 ISP 的 DNS 或公共 DNS 如 8.8.8.8),获取结果后缓存并返回给客户端。
  • DHCP 服务器:它可以为连接到网络的设备自动分配 IP 地址、网关、DNS 服务器等网络配置信息。
  • TFTP 服务器:用于简单的文件传输,常用于网络启动 (PXE boot) 或固件升级。

2. dnsmasq 的核心特点及配置指令

2.1. 核心特点

  • DNS 缓存:这是 dnsmasq 最常用的功能之一。它缓存了最近查询过的域名解析结果,当再次有相同查询时,可以直接从本地缓存中返回,大大加快了域名解析速度,并减少了对上游 DNS 服务器的请求。
  • DNS 转发:它将无法本地解析的 DNS 请求转发给配置的上游 DNS 服务器。
  • DHCP 服务:提供动态主机配置协议服务,自动为局域网内的设备分配 IP 地址、子网掩码、网关和 DNS 服务器地址。
  • 主机名解析:可以解析 /etc/hosts 文件中定义的主机名,这对于内部网络中的设备命名非常方便,无需在每个设备上修改 hosts 文件。
  • 自定义 DNS 记录:允许你为特定域名配置自定义的解析结果,例如将某个外部域名解析到内部 IP 地址。
  • DNSSEC 支持:可以配置为执行 DNSSEC 验证,增强 DNS 解析的安全性。
  • TFTP 服务:提供简单的 TFTP 文件传输服务。
  • IPv6 支持:全面支持 IPv6 的 DNS 和 DHCPv6 功能。

2.2 配置指令分类解析

dnsmasq 的核心配置文件是 /etc/dnsmasq.conf,你也可以通过在 conf-dir 指令中指定一个目录(例如 /etc/dnsmasq.d/)来加载多个小的配置文件,方便管理。

1. DNS 核心功能配置 (Caching & Forwarding)

这类指令控制 dnsmasq 作为 DNS 缓存服务器和转发器的基本行为。

  • listen-address=<IP 地址>: 指定 dnsmasq 监听 DNS 和 DHCP 请求的 IP 地址。例如,listen-address=127.0.0.1,192.168.1.100

  • port=<端口号>: 指定 dnsmasq 监听 DNS 查询的端口(默认是 53)。

  • no-resolv: 禁止 dnsmasq 读取 /etc/resolv.conf 来获取上游 DNS 服务器。

  • server=<IP 地址>

    指定 dnsmasq将 DNS 请求转发到的上游 DNS 服务器。可以有多行。

    • 示例:server=8.8.8.8 (Google DNS)。
  • server=/域名/IP:
    条件转发,将特定域名的查询转发给指定的上游 DNS 服务器。

    • 示例:server=/internal.com/192.168.1.254
  • server=/#/IP:

    将所有无法解析的域名都转发到指定的 IP 地址。

    • 示例:server=/#/127.0.0.1 (将不存在的域名指向本地)。
  • strict-order:

    强制 dnsmasq 严格按照 server 指令的顺序使用上游 DNS 服务器。

  • cache-size=<数量>:

    设置dnsmasq缓存的 DNS 记录数量。默认通常是 150。

    • 示例:cache-size=10000
  • min-ttl=<秒数>:

    为所有缓存的 DNS 记录设置一个最小 TTL 值,即使上游返回的 TTL 更短。

  • domain-needed:

    阻止对没有点(.)的非限定域名进行上游查询。

  • bogus-priv:

    阻止对私有 IP 地址范围的反向 DNS 查询 (PTR 记录) 发送到上游 DNS 服务器。


2. 本地解析与自定义记录

这类指令让你能够定义自己的 DNS 记录,覆盖公共 DNS 的解析,或为内部网络提供解析。

  • address=/域名/IP地址:

    为指定域名配置静态的 A 或 AAAA 记录。常用于本地覆盖或广告屏蔽。

    • 示例:address=/myapp.local/192.168.1.20address=/ad.tracker.com/0.0.0.0
  • cname=<源域名>,<目标域名>:

    配置本地 CNAME 记录,将一个域名指向另一个域名。

    • 示例:cname=old.example.com,new.example.com
  • ptr-record=<IP地址的in-addr.arpa或ip6.arpa形式>,<域名>:

    配置本地 PTR 记录,用于反向解析 IP 地址到域名。

    • 示例:ptr-record=5.1.168.192.in-addr.arpa,mydevice.local
  • txt-record=<域名>,<文本内容>: 配置本地 TXT 记录。

  • srv-record=<服务名>,<主机名>,<端口>,<优先级>,<权重>: 配置本地 SRV 记录。

  • mx-record=<域名>,<邮件服务器>,<优先级>: 配置本地 MX 记录。

  • expand-hosts: 自动将 domain 指令定义的前缀附加到 /etc/hosts 文件中的简单主机名。

  • domain=<域名>: 定义本地网络的域名后缀,常与 expand-hosts 结合使用。

  • hostsdir=<目录路径>: 从指定目录加载所有主机文件(类似 /etc/hosts 格式)。


3. DHCP 服务配置

如果你想让 dnsmasq 充当 DHCP 服务器,这些指令必不可少。

  • dhcp-range=<起始IP>,<结束IP>,[租期]:

    定义 DHCP 分配的 IP 地址范围和租期。

    • 示例:dhcp-range=192.168.1.100,192.168.1.200,12h
  • dhcp-option=<选项号>,<值>:

    为 DHCP 客户端配置额外的 DHCP 选项,如网关、DNS 服务器、NTP 服务器等。

    • 示例:dhcp-option=3,192.168.1.1 (设置网关)。
    • 示例:dhcp-option=6,192.168.1.10,8.8.8.8 (设置 DNS 服务器)。
  • dhcp-host=<MAC地址>,[IP地址],[主机名],[租期]:

    为特定 MAC 地址的设备分配静态 IP 地址(MAC 地址绑定)。

    • 示例:dhcp-host=00:11:22:33:44:55,192.168.1.50,mydevice,infinite
  • dhcp-authoritative: 声明 dnsmasq 是指定 DHCP 范围的权威 DHCP 服务器。

  • dhcp-leasefile=<文件路径>: 指定 DHCP 租约文件的位置。


4. 日志与调试

这些指令帮助你监控 dnsmasq 的运行情况和排查问题。

  • log-queries: 记录所有 DNS 查询到日志。
  • log-dhcp: 记录所有 DHCP 相关活动到日志。
  • log-facility=<文件路径>log-facility=syslog: 指定日志输出到哪里。
  • quiet-dhcp, quiet-ra, quiet-tftp: 抑制特定服务的详细日志,减少日志量。

5. 安全与性能

这些指令用于加强 dnsmasq 的安全性或优化其性能。

  • interface=<接口名>, except-interface=<接口名>: 指定 dnsmasq 监听或不监听的网卡接口。
  • bind-interfaces: 强制 dnsmasq 只绑定到 listen-addressinterface 中指定的 IP 地址或接口。
  • all-servers: 并发查询所有 server 指令指定的上游 DNS 服务器,并使用第一个响应。
  • dnssec: 启用 DNSSEC 验证(需要配置信任锚点)。
  • filterwin2k: 过滤掉 Windows 2000 等客户端发送的一些不符合 DNS 规范的 DNS 请求。

6. 模块化配置

这些指令让你的配置更加整洁和易于管理。

  • conf-dir=<目录路径>[,<文件后缀>]: 从指定目录加载所有以特定后缀结尾的配置文件。

    • 示例:conf-dir=/etc/dnsmasq.d/,*.conf
  • conf-file=<文件路径>: 加载一个特定的配置文件。


3. dnsmasq 的部署步骤

下面以 Linux 系统为例,详细说明 dnsmasq 的部署步骤。

3.1. 规划

在部署之前,需要明确几个关键点:

  • 服务器 IP 地址dnsmasq 服务器需要一个静态 IP 地址,例如 192.168.1.1
  • 网络范围:如果你打算使用 DHCP 功能,需要确定 DHCP 分配的 IP 地址范围。
  • 上游 DNS 服务器:选择可靠的上游 DNS 服务器,例如你的 ISP 的 DNS、Google Public DNS (8.8.8.8, 8.8.4.4) 或 Cloudflare DNS (1.1.1.1, 1.0.0.1)。
  • 端口:DNS 服务使用 UDP/TCP 53 端口,DHCP 服务使用 UDP 67/68 端口。确保这些端口没有被其他服务占用,并配置防火墙允许流量。

3.2. 安装 dnsmasq

在大多数 Linux 发行版中,dnsmasq 可以通过包管理器直接安装。

  • Debian/Ubuntu/Raspbian

    1
    2
    sudo apt update
    sudo apt install dnsmasq
  • CentOS/RHEL/Fedora

    1
    sudo yum install dnsmasq # 或 sudo dnf install dnsmasq

3.3. 配置 dnsmasq

dnsmasq 的主配置文件通常位于 /etc/dnsmasq.conf。安装后,该文件通常包含大量注释,你可以根据需要取消注释并修改。

重要提示:在修改配置文件之前,建议备份原始文件:

1
sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.bak

以下是一些常见的配置选项:

3.3.1. 基本 DNS 转发与缓存配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# /etc/dnsmasq.conf

# 1. 监听地址
# dnsmasq 将监听这些IP地址上的DNS和DHCP请求。
# 0.0.0.0 表示监听所有可用接口。
# 如果只希望在特定接口或IP上监听,请指定IP地址。
listen-address=127.0.0.1,192.168.1.100 # 替换为你的服务器内网IP,例如你的树莓派IP

# 2. 不从 /etc/resolv.conf 读取上游 DNS 服务器
# 默认情况下,dnsmasq 会读取 /etc/resolv.conf 来获取上游 DNS 服务器。
# 如果你希望手动指定上游服务器,请取消注释此行。
no-resolv

# 3. 指定上游 DNS 服务器
# 这些是 dnsmasq 将转发请求到的外部 DNS 服务器。
# 可以指定多个,dnsmasq 会根据响应时间选择最佳的。
server=8.8.8.8 # Google Public DNS
server=8.8.4.4 # Google Public DNS
# server=1.1.1.1 # Cloudflare DNS
# server=1.0.0.1 # Cloudflare DNS

# 4. 启用缓存
# 设置缓存大小。默认是 150。增加缓存大小可以提高性能。
cache-size=10000

# 5. 允许哪些网络查询 (访问控制)
# 默认情况下,dnsmasq 接受来自所有接口的查询。
# 如果你希望限制,可以使用 interface 或 except-interface。
# interface=eth0 # 只监听 eth0 接口
# except-interface=lo # 除了 lo 接口,监听所有接口

# 6. 忽略私有反向查找
# 忽略私有 IP 地址(如 192.168.x.x)的反向查找请求,避免向公共 DNS 服务器发送这些请求。
bogus-priv

# 7. 忽略非路由地址空间的反向查找
# 忽略来自非路由地址空间的反向查找请求。
domain-needed

3.3.2. 本地主机名解析

dnsmasq 可以解析 /etc/hosts 文件中的主机名。

1
2
3
4
5
6
7
8
9
10
11
12
13
# /etc/dnsmasq.conf

# 8. 从 /etc/hosts 读取主机名
# dnsmasq 默认会读取 /etc/hosts 文件。
# 如果你在 /etc/hosts 中添加了类似 "192.168.1.20 myprinter" 的条目,
# 那么局域网内的设备就可以通过 "myprinter" 访问该设备。
# addn-hosts=/etc/dnsmasq.d/myhosts.conf # 也可以指定额外的 hosts 文件

# 9. 扩展主机名(可选)
# 如果你的域名是 localnet,并且你在 /etc/hosts 中定义了 "mydevice",
# 那么 "mydevice.localnet" 也会被解析。
# expand-hosts
# domain=localnet

3.3.3. DHCP 服务器配置 (可选)

如果你希望 dnsmasq 也作为 DHCP 服务器,为局域网内的设备分配 IP 地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# /etc/dnsmasq.conf

# 10. 启用 DHCP 服务
# dhcp-range=<start-ip>,<end-ip>,<lease-time>
# 例如:为 192.168.1.100 到 192.168.1.200 的 IP 地址范围分配,租期 12 小时。
dhcp-range=192.168.1.100,192.168.1.200,12h

# 11. 指定网关 (router)
# dhcp-option=3,<gateway-ip>
dhcp-option=3,192.168.1.1 # 你的路由器IP

# 12. 指定 DNS 服务器 (dhcp-option=6)
# 默认情况下,dnsmasq 会将自己作为 DNS 服务器分配给客户端。
# 如果你想指定其他 DNS 服务器,可以取消注释此行。
# dhcp-option=6,8.8.8.8,8.8.4.4

# 13. 静态 IP 地址分配 (MAC 地址绑定)
# dhcp-host=<mac-address>,<ip-address>,<hostname>,<lease-time>
# 例如:为 MAC 地址为 00:11:22:33:44:55 的设备分配 192.168.1.50,主机名为 "mydevice",永不超时。
# dhcp-host=00:11:22:33:44:55,192.168.1.50,mydevice,infinite

# 14. DHCP 日志 (可选)
# log-dhcp

3.3.4. 高级 DNS 配置

  • **阻止特定域名 (黑名单)**:

    1
    2
    3
    4
    5
    6
    # 将这些域名解析到 0.0.0.0 (或 127.0.0.1) 来阻止访问
    address=/doubleclick.net/0.0.0.0
    address=/ad.example.com/0.0.0.0

    # 也可以使用外部文件来管理黑名单
    # conf-file=/etc/dnsmasq.d/adblock.conf

    adblock.conf 中每行一个 address=/domain/0.0.0.0

  • **自定义 DNS 记录 (本地覆盖)**:

    1
    2
    3
    4
    5
    6
    7
    8
    # 将 myapp.local 解析到内部服务器 IP
    address=/myapp.local/192.168.1.20

    # 将 www.external-service.com 解析到内部测试服务器 IP
    address=/www.external-service.com/192.168.1.30

    # CNAME 记录
    cname=oldname.example.com,newname.example.com
  • **条件转发 (Conditional Forwarding)**: 将特定域名的查询转发给特定的上游 DNS 服务器。

    1
    2
    # 将 example.com 域名的查询转发给 192.168.1.254
    server=/example.com/192.168.1.254

    这在企业环境中,需要将内部域名的解析请求发送到内部 DNS 服务器时非常有用。

  • 日志记录

    1
    2
    3
    # 启用所有日志
    log-queries
    log-facility=/var/log/dnsmasq.log # 指定日志文件

3.4. 启动/重启 dnsmasq 服务

配置完成后,需要启动或重启 dnsmasq 服务以使更改生效。

1
2
sudo systemctl restart dnsmasq
sudo systemctl enable dnsmasq # 设置开机自启

3.5. 配置客户端使用你的 dnsmasq 服务器

这是最后一步,确保你的设备使用你部署的 dnsmasq 服务器进行 DNS 解析。

  • 手动配置:在你的电脑、手机或路由器上,手动将 DNS 服务器地址设置为你 dnsmasq 服务器的 IP 地址(例如 192.168.1.100)。
  • **通过 DHCP (如果 dnsmasq 也是 DHCP 服务器)**:如果 dnsmasq 正在提供 DHCP 服务,它会自动将自己的 IP 地址作为 DNS 服务器分配给客户端。你需要确保网络中没有其他 DHCP 服务器与 dnsmasq 冲突。

4. 故障排除 (Troubleshooting)

  • 检查服务状态

    1
    sudo systemctl status dnsmasq

    查看服务是否正在运行,是否有错误信息。

  • 检查日志

    1
    2
    sudo journalctl -u dnsmasq # 查看 systemd 日志
    # 或者查看你配置的日志文件,如 /var/log/dnsmasq.log

    日志会告诉你 dnsmasq 启动时遇到的问题,或者它处理 DNS 查询的详细信息。

  • 使用 dignslookup 测试: 直接向你的 dnsmasq 服务器发送查询请求,检查解析是否正常。

    1
    2
    dig @192.168.1.100 www.google.com # 替换为你的 dnsmasq IP
    dig @192.168.1.100 myapp.local # 测试本地自定义解析
  • 检查防火墙: 确保防火墙允许 UDP/TCP 53 端口(DNS)和 UDP 67/68 端口(DHCP)的流量。

    1
    2
    sudo ufw status # 如果使用 UFW
    # 或者查看 iptables 规则
  • 检查端口占用: 确保 53 端口没有被其他 DNS 服务(如 systemd-resolved)占用。

    1
    sudo netstat -tulnp | grep :53

    如果 systemd-resolved 正在监听 53 端口,你可能需要禁用它或将其配置为不监听 53 端口,以便 dnsmasq 可以接管。