Dnsmasq 服务搭建完全教程 / 第 12 章:最佳实践
第 12 章:最佳实践
12.1 安全加固
12.1.1 最小权限原则
# /etc/dnsmasq.d/90-security.conf
# 以非 root 用户运行
user=dnsmasq
group=dnsmasq
# 创建专用用户
sudo useradd -r -s /usr/sbin/nologin -d /var/lib/dnsmasq dnsmasq
# 设置文件权限
sudo chown -R dnsmasq:dnsmasq /var/lib/dnsmasq
sudo chown -R dnsmasq:dnsmasq /var/log/dnsmasq
sudo chmod 750 /var/lib/dnsmasq
sudo chmod 750 /var/log/dnsmasq
12.1.2 网络访问限制
# 只监听特定接口
bind-interfaces
listen-address=127.0.0.1,192.168.1.1
except-interface=eth0
# 禁止 DNS 放大攻击
# 不响应来自外网的 DNS 查询
# 通过 iptables 限制
sudo iptables -A INPUT -p udp --dport 53 -i eth0 -j DROP
sudo iptables -A INPUT -p tcp --dport 53 -i eth0 -j DROP
12.1.3 DNS 安全配置
# 防 DNS 重绑定攻击
stop-dns-rebind
rebind-localhost-ok
rebind-domain-ok=/home.lan/
# 过滤私有 IP 的反向查询
bogus-priv
# 禁止转发私有域名到公网
local=/home.lan/
local=/168.192.in-addr.arpa/
# DNSSEC(可选,可能影响性能)
# dnssec
# dnssec-check-unsigned
12.1.4 防火墙规则
#!/bin/bash
# /usr/local/bin/setup-firewall.sh
# 清空规则
iptables -F INPUT
# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
# 允许 LAN 访问 DNS
iptables -A INPUT -p udp --dport 53 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 53 -s 192.168.1.0/24 -j ACCEPT
# 允许 LAN 访问 DHCP
iptables -A INPUT -p udp --dport 67 -s 192.168.1.0/24 -j ACCEPT
# 允许 SSH
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# 拒绝其他所有
iptables -A INPUT -j DROP
# 保存规则
sudo iptables-save > /etc/iptables/rules.v4
12.2 性能调优
12.2.1 缓存优化
# /etc/dnsmasq.d/91-performance.conf
# 缓存大小(根据设备数量调整)
cache-size=1000 # 家庭/小型办公
# cache-size=5000 # 中型网络
# cache-size=10000 # 大型网络
# 最小缓存 TTL(秒),防止过快过期
min-cache-ttl=300
# 负向缓存 TTL(解析失败也缓存)
neg-ttl=60
# 本地域名 TTL
local-ttl=300
12.2.2 缓存大小估算表
| 网络规模 | 设备数 | 每日查询量 | 推荐 cache-size | 内存占用 |
|---|
| 家庭 | < 20 | < 10K | 150-500 | ~50 KB |
| 小型办公 | 20-100 | 10K-50K | 500-2000 | ~200 KB |
| 中型网络 | 100-500 | 50K-200K | 2000-5000 | ~500 KB |
| 大型网络 | 500+ | 200K+ | 5000-10000 | ~1 MB |
12.2.3 上游 DNS 选择
# 选择响应快、可靠的上游 DNS
# 国内推荐
server=223.5.5.5 # 阿里 DNS(延迟低)
server=119.29.29.29 # 腾讯 DNS(延迟低)
server=114.114.114.114 # 114 DNS(稳定)
# 国际推荐
server=8.8.8.8 # Google DNS
server=1.1.1.1 # Cloudflare DNS
# 严格顺序(使用延迟最低的)
strict-order
# 并行查询(默认,最快响应优先)
# all-servers
12.2.4 系统级优化
# 增大文件描述符限制
# /etc/security/limits.conf
dnsmasq soft nofile 4096
dnsmasq hard nofile 8192
# 增大 UDP 缓冲区
# /etc/sysctl.conf
net.core.rmem_max=8388608
net.core.wmem_max=8388608
net.core.rmem_default=1048576
net.core.wmem_default=1048576
# 应用 sysctl
sudo sysctl -p
12.3 运维规范
12.3.1 配置管理
推荐的配置目录结构:
/etc/dnsmasq.conf # 主配置(仅包含 conf-dir)
/etc/dnsmasq.d/
├── 00-base.conf # 基础设置(监听、缓存)
├── 01-upstream.conf # 上游 DNS
├── 02-local-domain.conf # 本地域名
├── 10-dhcp-main.conf # 主网络 DHCP
├── 11-dhcp-vlan10.conf # VLAN 10 DHCP
├── 12-dhcp-vlan20.conf # VLAN 20 DHCP
├── 20-pxe.conf # PXE 引导(可选)
├── 30-custom-records.conf # 自定义 DNS 记录
├── 50-filter.conf # 域名过滤
├── 90-security.conf # 安全配置
├── 91-performance.conf # 性能配置
└── 99-debug.conf # 调试配置(默认禁用)
/etc/dnsmasq.hosts # 自定义 hosts 文件
/var/lib/misc/dnsmasq.leases # DHCP 租约文件
/var/log/dnsmasq/dnsmasq.log # 日志文件
12.3.2 版本控制
# 将配置纳入 Git 版本控制
cd /etc
sudo git init
sudo git add dnsmasq.conf dnsmasq.d/ dnsmasq.hosts
sudo git commit -m "Initial Dnsmasq configuration"
# 配置变更后提交
sudo git add -A
sudo git commit -m "feat: add IoT VLAN DHCP config"
# 查看变更历史
sudo git log --oneline
sudo git diff HEAD~1
12.3.3 备份策略
#!/bin/bash
# /usr/local/bin/backup-dnsmasq.sh
BACKUP_DIR="/backup/dnsmasq"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/dnsmasq_backup_$TIMESTAMP.tar.gz"
mkdir -p "$BACKUP_DIR"
tar czf "$BACKUP_FILE" \
/etc/dnsmasq.conf \
/etc/dnsmasq.d/ \
/etc/dnsmasq.hosts \
/var/lib/misc/dnsmasq.leases
# 保留最近 30 天的备份
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
echo "Backup completed: $BACKUP_FILE"
# Cron 定时备份
# 每天凌晨 2 点备份
0 2 * * * root /usr/local/bin/backup-dnsmasq.sh >> /var/log/dnsmasq-backup.log 2>&1
12.3.4 监控与告警
#!/bin/bash
# /usr/local/bin/healthcheck-dnsmasq.sh
# 健康检查脚本,配合 cron 使用
# 每 5 分钟检查一次
# */5 * * * * root /usr/local/bin/healthcheck-dnsmasq.sh
LOGFILE="/var/log/dnsmasq-health.log"
ALERT_FILE="/tmp/dnsmasq-alert-sent"
check_service() {
if ! systemctl is-active --quiet dnsmasq; then
echo "[$(date)] CRITICAL: Dnsmasq is not running" >> "$LOGFILE"
systemctl restart dnsmasq
if [ $? -eq 0 ]; then
echo "[$(date)] INFO: Dnsmasq restarted successfully" >> "$LOGFILE"
fi
return 1
fi
return 0
}
check_dns() {
local result=$(dig @127.0.0.1 baidu.com +short +timeout=3 2>/dev/null)
if [ -z "$result" ]; then
echo "[$(date)] CRITICAL: DNS resolution failed" >> "$LOGFILE"
return 1
fi
return 0
}
check_memory() {
local rss=$(ps -o rss= -p $(pidof dnsmasq) 2>/dev/null)
if [ -n "$rss" ] && [ "$rss" -gt 102400 ]; then
echo "[$(date)] WARNING: Memory usage high: ${rss}KB" >> "$LOGFILE"
fi
}
check_service && check_dns && check_memory
12.4 家庭网络部署方案
12.4.1 推荐架构
Internet
│
│ (WAN - eth0)
┌──┴──────────────────┐
│ 路由器/服务器 │
│ Dnsmasq │
│ 192.168.1.1 │
│ │
│ eth1 (LAN) ───────┼──→ 交换机 ──→ 所有设备
└─────────────────────┘
网络分配:
- 网关/DNS: 192.168.1.1
- 静态设备: 192.168.1.10-49 (打印机、NAS、摄像头)
- DHCP 池: 192.168.1.100-200 (手机、电脑、平板)
- IoT 设备: 192.168.1.200-250
12.4.2 完整配置
# /etc/dnsmasq.d/00-base.conf
bind-interfaces
listen-address=127.0.0.1,192.168.1.1
port=53
cache-size=500
min-cache-ttl=300
neg-ttl=60
domain=home.lan
expand-hosts
local=/home.lan/
# /etc/dnsmasq.d/01-upstream.conf
server=223.5.5.5
server=119.29.29.29
server=8.8.8.8
no-resolv
# /etc/dnsmasq.d/10-dhcp.conf
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
# 静态绑定
dhcp-host=aa:bb:cc:dd:ee:01,192.168.1.10,nas,24h
dhcp-host=aa:bb:cc:dd:ee:02,192.168.1.20,printer,infinite
# /etc/dnsmasq.d/50-filter.conf
# 广告屏蔽
conf-file=/etc/dnsmasq.adblock
# /etc/dnsmasq.d/90-security.conf
stop-dns-rebind
rebind-localhost-ok
bogus-priv
except-interface=eth0
# /etc/dnsmasq.hosts
192.168.1.1 gateway gateway.home.lan
192.168.1.10 nas nas.home.lan
192.168.1.20 printer printer.home.lan
192.168.1.30 camera-front camera-front.home.lan
192.168.1.31 camera-back camera-back.home.lan
12.4.3 OpenWrt 集成
# OpenWrt 使用 UCI 管理 Dnsmasq
# 配置文件:/etc/config/dhcp
# 查看当前配置
uci show dhcp
# 设置上游 DNS
uci set dhcp.@dnsmasq[0].server='223.5.5.5'
uci set dhcp.@dnsmasq[0].server='8.8.8.8'
# 设置缓存大小
uci set dhcp.@dnsmasq[0].cachesize='500'
# 添加静态租约
uci add dhcp host
uci set dhcp.@host[-1].mac='AA:BB:CC:DD:EE:01'
uci set dhcp.@host[-1].ip='192.168.1.10'
uci set dhcp.@host[-1].name='nas'
# 提交配置
uci commit dhcp
# 重启服务
/etc/init.d/dnsmasq restart
12.5 企业网络部署方案
12.5.1 推荐架构
Internet
│
┌───┴───┐
│ 防火墙 │
└───┬───┘
│
┌────────┼────────┐
│ │ │
┌────┴───┐ │ ┌────┴───┐
│ Dnsmasq│ │ │ Dnsmasq│
│ 主节点 │ │ │ 备节点 │
│ .1.1 │ │ │ .1.2 │
└────┬───┘ │ └────┬───┘
│ │ │
└────────┼────────┘
│
VIP: .1.254
│
┌──────────────┼──────────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ VLAN 10 │ │ VLAN 20 │ │ VLAN 30 │
│ 办公网络 │ │ 访客网络 │ │ IoT 网络 │
│ .10.0/24│ │ .20.0/24│ │ .30.0/24│
└─────────┘ └─────────┘ └─────────┘
12.5.2 多 VLAN 企业配置
# /etc/dnsmasq.d/00-base.conf
bind-interfaces
domain=corp.lan
expand-hosts
no-hosts
addn-hosts=/etc/dnsmasq.hosts
# /etc/dnsmasq.d/01-upstream.conf
server=/corp.lan/10.0.0.53 # 企业内网 DNS
server=223.5.5.5 # 公网 DNS
no-resolv
# /etc/dnsmasq.d/10-vlan10-office.conf
listen-address=192.168.10.1
interface=eth1.10
dhcp-range=set:office,192.168.10.100,192.168.10.200,255.255.255.0,12h
dhcp-option=tag:office,option:router,192.168.10.1
dhcp-option=tag:office,option:dns-server,192.168.10.1,10.0.0.53
dhcp-option=tag:office,option:ntp-server,10.0.0.1
dhcp-option=tag:office,option:domain-name,"office.corp.lan"
# /etc/dnsmasq.d/11-vlan20-guest.conf
listen-address=192.168.20.1
interface=eth1.20
dhcp-range=set:guest,192.168.20.100,192.168.20.200,255.255.255.0,2h
dhcp-option=tag:guest,option:router,192.168.20.1
dhcp-option=tag:guest,option:dns-server,223.5.5.5
# /etc/dnsmasq.d/12-vlan30-iot.conf
listen-address=192.168.30.1
interface=eth1.30
dhcp-range=set:iot,192.168.30.100,192.168.30.250,255.255.255.0,168h
dhcp-option=tag:iot,option:router,192.168.30.1
dhcp-option=tag:iot,option:dns-server,192.168.30.1
# 安全:访客网络禁止访问内网
# 通过 iptables 实现,不在 Dnsmasq 中配置
12.5.3 企业级监控集成
# Prometheus + Grafana 监控 Dnsmasq
# docker-compose.monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
dnsmasq-exporter:
image: google/dnsmasq_exporter:latest
command:
- "--dnsmasq.address=http://127.0.0.1:53"
ports:
- "9153:9153"
network_mode: host
12.6 容器化部署最佳实践
12.6.1 生产级 Docker Compose
# docker-compose.prod.yml
version: '3.8'
services:
dnsmasq:
image: jpillora/dnsmasq:latest
container_name: dnsmasq
restart: always
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
- ./config/dnsmasq.conf:/etc/dnsmasq.conf:ro
- ./config/dnsmasq.d:/etc/dnsmasq.d:ro
- ./config/hosts:/etc/dnsmasq.hosts:ro
- dnsmasq-leases:/var/lib/misc
- dnsmasq-logs:/var/log/dnsmasq
- /etc/localtime:/etc/localtime:ro
environment:
- TZ=Asia/Shanghai
- HTTP_USER=admin
- HTTP_PASS_FILE=/run/secrets/admin_password
secrets:
- admin_password
deploy:
resources:
limits:
cpus: '0.5'
memory: 128M
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
healthcheck:
test: ["CMD", "nslookup", "baidu.com", "127.0.0.1"]
interval: 30s
timeout: 5s
retries: 3
volumes:
dnsmasq-leases:
dnsmasq-logs:
secrets:
admin_password:
file: ./secrets/admin_password.txt
12.7 配置模板与速查
12.7.1 最小可用配置
# 只需 3 行即可运行
listen-address=192.168.1.1
interface=eth1
dhcp-range=192.168.1.100,192.168.1.200,24h
12.7.2 功能完整配置
# 15 行覆盖基本需求
bind-interfaces
listen-address=127.0.0.1,192.168.1.1
domain=home.lan
expand-hosts
server=223.5.5.5
server=8.8.8.8
no-resolv
cache-size=500
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
stop-dns-rebind
except-interface=eth0
12.7.3 常用命令速查
# 服务管理
systemctl start dnsmasq # 启动
systemctl stop dnsmasq # 停止
systemctl restart dnsmasq # 重启
systemctl reload dnsmasq # 热重载配置
systemctl status dnsmasq # 查看状态
# 配置检查
dnsmasq --test # 语法检查
dnsmasq --version # 查看版本
dig @127.0.0.1 example.com # 测试 DNS
cat /var/lib/misc/dnsmasq.leases # 查看租约
# 调试
dnsmasq --no-daemon --log-facility=- # 前台运行
journalctl -u dnsmasq -f # 实时日志
tcpdump -i eth1 -n port 53 # 抓包分析
# 监控
kill -USR1 $(pidof dnsmasq) # 输出统计
kill -USR2 $(pidof dnsmasq) # 输出租约信息
ps aux | grep dnsmasq # 进程状态
12.8 版本升级指南
12.8.1 升级前检查
# 1. 备份当前配置
sudo tar czf /backup/dnsmasq-pre-upgrade.tar.gz /etc/dnsmasq.*
# 2. 记录当前版本
dnsmasq --version > /backup/dnsmasq-version-before.txt
# 3. 检查新版本 changelog
# http://www.thekelleys.org.uk/dnsmasq/CHANGELOG
# 4. 在测试环境验证
12.8.2 升级步骤
# 使用包管理器升级
sudo apt update && sudo apt upgrade dnsmasq
# 检查配置兼容性
sudo dnsmasq --test
# 重启服务
sudo systemctl restart dnsmasq
# 验证功能
dig @127.0.0.1 www.baidu.com
cat /var/lib/misc/dnsmasq.leases
12.9 小结
| 类别 | 关键实践 | 重要程度 |
|---|
| 安全 | bind-interfaces + 防火墙 | ⭐⭐⭐ |
| 安全 | stop-dns-rebind + bogus-priv | ⭐⭐⭐ |
| 性能 | 合理 cache-size + min-cache-ttl | ⭐⭐ |
| 运维 | Git 管理配置 + 定期备份 | ⭐⭐⭐ |
| 运维 | 健康检查 + 告警 | ⭐⭐ |
| 部署 | no-hosts + addn-hosts | ⭐⭐ |
| 部署 | 分环境配置文件 | ⭐⭐ |
12.10 扩展阅读