强曰为道

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

第 02 章:安装与初始配置

第 02 章:安装与初始配置

2.1 安装 Dnsmasq

2.1.1 Debian / Ubuntu

# 更新包索引
sudo apt update

# 安装 Dnsmasq
sudo apt install dnsmasq

# 验证安装
dnsmasq --version

注意:Ubuntu 18.04+ 默认使用 systemd-resolved 占用 53 端口,需要先释放:

# 检查 53 端口占用
sudo ss -tlnp | grep :53

# 方法 1:停止 systemd-resolved(推荐)
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved

# 方法 2:修改 systemd-resolved 配置,让它不监听 53
# 编辑 /etc/systemd/resolved.conf
sudo tee -a /etc/systemd/resolved.conf <<'EOF'
[Resolve]
DNSStubListener=no
EOF

# 创建 resolv.conf 指向 Dnsmasq
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
sudo systemctl restart systemd-resolved

2.1.2 CentOS / RHEL / Fedora

# CentOS 7 / RHEL 7
sudo yum install dnsmasq

# CentOS 8+ / RHEL 8+ / Fedora
sudo dnf install dnsmasq

# 验证安装
dnsmasq --version

注意:CentOS 7+ 默认使用 firewalld,需放行 DNS/DHCP 端口:

sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --permanent --add-service=dhcp
sudo firewall-cmd --reload

2.1.3 Alpine Linux

# 安装
apk add dnsmasq

# 设置开机启动
rc-update add dnsmasq default

# 启动服务
rc-service dnsmasq start

2.1.4 Arch Linux

sudo pacman -S dnsmasq
sudo systemctl enable --now dnsmasq

2.1.5 macOS (Homebrew)

brew install dnsmasq

# 编辑配置
brew edit dnsmasq
# 或直接编辑
nano /usr/local/etc/dnsmasq.conf

# 启动服务
sudo brew services start dnsmasq

2.1.6 从源码编译

适用于需要最新版本或自定义编译选项的场景:

# 安装编译依赖
sudo apt install build-essential pkg-config

# 下载源码
cd /tmp
wget http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.90.tar.gz
tar xzf dnsmasq-2.90.tar.gz
cd dnsmasq-2.90

# 查看编译选项
head -30 Makefile

# 编译(默认支持 IPv6)
make

# 安装
sudo make install

# 验证
which dnsmasq
dnsmasq --version

自定义编译选项

# 编辑 Makefile 头部,修改 COPTS 变量
# 例如禁用 IPv6、启用 Lua 脚本支持:
# COPTS = -DHAVE_IPV6 -DNO_LUA

# 或通过命令行传入
make COPTS="-DNO_IPV6 -DHAVE_LUASCRIPT"
sudo make install

2.2 包管理器安装 vs 源码编译

维度包管理器源码编译
安装速度秒级分钟级
版本发行版维护(可能较旧)最新版本
依赖自动解决手动安装
升级apt upgrade / dnf update手动重新编译
编译选项固定可自定义
推荐场景大多数情况需要特定版本或功能

2.3 配置文件结构

Dnsmasq 使用单一配置文件,支持目录式片段加载:

/etc/dnsmasq.conf              ← 主配置文件
/etc/dnsmasq.d/                ← 配置片段目录
/etc/dnsmasq.d/*.conf          ← 自动加载的 .conf 文件
/etc/dnsmasq.d/bak/            ← 备份/禁用的配置
/etc/hosts                     ← 系统 hosts 文件(自动读取)
/etc/resolv.conf               ← 上游 DNS 指向(自动读取)
/var/lib/misc/dnsmasq.leases   ← DHCP 租约文件

2.3.1 配置文件语法

# 注释行以 # 开头
# 这是注释

# 每行一个选项,格式为:
# 选项=值
# 选项=值1,值2,值3       ← 列表用逗号分隔
# 选项                   ← 布尔选项无需值
# --选项=值              ← 两种写法等价

# 示例
listen-address=127.0.0.1,192.168.1.1
port=53
cache-size=1000
domain=home.lan
log-queries

2.3.2 推荐的配置组织方式

不要直接修改 /etc/dnsmasq.conf 主文件,而是使用 /etc/dnsmasq.d/ 目录:

# 保留主配置文件为模板,仅启用配置目录加载
sudo grep -v "^#" /etc/dnsmasq.conf | grep -v "^$" | head -20

# 在 dnsmasq.conf 末尾确认包含这行(多数发行版默认有):
# conf-dir=/etc/dnsmasq.d/,*.conf

创建功能模块化配置:

sudo tee /etc/dnsmasq.d/00-base.conf <<'EOF'
# === 基础 DNS 配置 ===
listen-address=127.0.0.1,192.168.1.1
bind-interfaces
port=53
cache-size=500
neg-ttl=60
domain=home.lan
expand-hosts
EOF

sudo tee /etc/dnsmasq.d/01-upstream.conf <<'EOF'
# === 上游 DNS ===
server=8.8.8.8
server=8.8.4.4
server=114.114.114.114
no-resolv
EOF

sudo tee /etc/dnsmasq.d/02-dhcp.conf <<'EOF'
# === DHCP 配置 ===
interface=eth1
dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,24h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.1
EOF

2.4 核心命令行选项

2.4.1 常用选项速查表

选项说明示例
--conf-file=FILE指定配置文件--conf-file=/etc/dnsmasq.conf
--conf-dir=DIR加载目录中的配置片段--conf-dir=/etc/dnsmasq.d/,*.conf
--no-daemon前台运行(调试用)-d--no-daemon
--log-queries记录 DNS 查询日志--log-queries
--log-facility=FILE日志输出文件--log-facility=/var/log/dnsmasq.log
--port=PORTDNS 监听端口--port=5353
--listen-address=IP监听地址--listen-address=127.0.0.1
--interface=IFACE监听指定接口--interface=eth1
--except-interface=IFACE排除接口--except-interface=lo
--cache-size=NDNS 缓存条目数--cache-size=1000
--pid-file=FILEPID 文件路径--pid-file=/run/dnsmasq.pid
--user=USER运行用户--user=dnsmasq
--test检查配置语法--test

2.4.2 命令行与配置文件对照

# 命令行
dnsmasq --port=5353 --cache-size=500 --log-queries

# 等价的配置文件
port=5353
cache-size=500
log-queries

优先级规则:命令行选项 > 配置文件选项。命令行中重复的选项,后面的覆盖前面的。

2.5 首次启动

2.5.1 检查配置语法

# 测试配置文件是否正确
dnsmasq --test

# 输出 "dnsmasq: syntax check OK." 表示配置无误
# 输出错误信息则需修复对应行

2.5.2 启动服务

# 使用 systemd(推荐)
sudo systemctl start dnsmasq
sudo systemctl enable dnsmasq    # 开机自启
sudo systemctl status dnsmasq    # 查看状态

# 查看服务日志
sudo journalctl -u dnsmasq -f    # 实时跟踪
sudo journalctl -u dnsmasq --since "1 hour ago"  # 最近1小时

2.5.3 手动前台启动(调试)

# 前台运行,输出日志到终端
sudo dnsmasq --no-daemon --log-queries --log-facility=-

# 指定配置文件
sudo dnsmasq --no-daemon --conf-file=/etc/dnsmasq.conf

2.5.4 验证 DNS 服务

# 使用 dig 查询
dig @127.0.0.1 www.baidu.com

# 使用 nslookup
nslookup www.baidu.com 127.0.0.1

# 使用 host
host www.baidu.com 127.0.0.1

预期输出(dig):

;; ANSWER SECTION:
www.baidu.com.    300    IN    A    110.242.68.66
;; Query time: 28 msec        ← 首次查询(从上游获取)
;; SERVER: 127.0.0.1#53

# 再次查询
;; Query time: 0 msec         ← 缓存命中,耗时接近 0
;; SERVER: 127.0.0.1#53

2.6 systemd 服务文件详解

Dnsmasq 的 systemd 服务单元文件通常位于 /lib/systemd/system/dnsmasq.service

[Unit]
Description=DHCP and DNS caching server
After=network.target
Documentation=man:dnsmasq(8)

[Service]
Type=dbus
BusName=org.freedesktop.NetworkManager.dnsmasq
ExecStart=/usr/sbin/dnsmasq -k --log-facility=/var/log/dnsmasq.log
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

关键参数说明

参数说明
Type=dbus通过 D-Bus 注册服务(NetworkManager 集成)
-k前台运行(systemd 要求,替代 daemon 模式)
ExecReload支持 systemctl reload dnsmasq 热重载配置
Restart=on-failure异常退出后自动重启

2.6.1 自定义 systemd 服务

如果需要自定义启动参数:

# 创建 override 文件(不修改原文件)
sudo systemctl edit dnsmasq

# 在编辑器中写入:
[Service]
ExecStart=
ExecStart=/usr/sbin/dnsmasq -k --conf-file=/etc/dnsmasq-custom.conf
# 重新加载并重启
sudo systemctl daemon-reload
sudo systemctl restart dnsmasq

2.7 完整的最小配置示例

以下是一个功能完备的最小配置,适合家庭网络快速部署:

sudo tee /etc/dnsmasq.d/home-network.conf <<'EOF'
# ============================================
# Dnsmasq 家庭网络最小配置
# ============================================

# --- DNS 基础配置 ---
listen-address=127.0.0.1,192.168.1.1
bind-interfaces
port=53
cache-size=500
min-cache-ttl=300
neg-ttl=60

# --- 上游 DNS ---
server=223.5.5.5
server=119.29.29.29
server=8.8.8.8
no-resolv
no-poll

# --- 本地域名 ---
domain=home.lan
expand-hosts
local=/home.lan/

# --- DHCP 配置 ---
interface=eth1
dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,24h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.1
dhcp-authoritative

# --- 日志 ---
log-queries
log-facility=/var/log/dnsmasq.log
EOF

验证并启动:

# 检查语法
sudo dnsmasq --test

# 重启服务
sudo systemctl restart dnsmasq

# 验证 DNS
dig @192.168.1.1 www.baidu.com

# 验证 DHCP(在另一台设备上)
# 断开重连网络,检查是否获得 192.168.1.100-200 范围的 IP

2.8 配置热重载

修改配置后无需重启服务,可以发送 SIGHUP 信号让 Dnsmasq 重新加载:

# 方法 1:systemctl reload
sudo systemctl reload dnsmasq

# 方法 2:手动发送信号
sudo kill -HUP $(pidof dnsmasq)

# 方法 3:使用 dnsmasq 的 D-Bus 接口
sudo dbus-send --system --dest=uk.org.thekelleys.dnsmasq \
  /uk/org/thekelleys/dnsmasq \
  uk.org.thekelleys.dnsmasq.Reload

注意:SIGHUP 会重新读取配置文件、hosts 文件和域名列表,但不会中断现有连接。DHCP 租约文件不会重新加载。

2.9 端口冲突处理

常见端口冲突及解决方案:

冲突服务端口解决方案
systemd-resolved53停用或配置 DNSStubListener=no
dnsmasq (另一个实例)53kill 旧进程或修改端口
named (BIND)53systemctl stop named
NetworkManager 内置 dnsmasq53禁用 NM 的 dns=dnsmasq
其他 DHCP 服务67停止 isc-dhcp-server
# 查看所有 53 端口占用
sudo ss -ulnp | grep :53
sudo ss -tlnp | grep :53

# 查看 67 端口(DHCP)
sudo ss -ulnp | grep :67

2.10 小结

要点说明
安装方式包管理器(推荐)或源码编译
配置文件/etc/dnsmasq.conf + /etc/dnsmasq.d/*.conf
配置检查dnsmasq --test
启动管理systemctl start/stop/restart/reload dnsmasq
端口冲突优先检查 systemd-resolved
热重载systemctl reload dnsmasq(发送 SIGHUP)

2.11 扩展阅读