第 10 章:响应策略区域(RPZ)
本章概述
RPZ(Response Policy Zone,响应策略区域)是 BIND 的安全特性,允许通过 DNS 层面拦截恶意域名、钓鱼网站和广告。本章讲解 RPZ 的原理、规则编写、日志审计和最佳实践。
10.1 RPZ 基础
10.1.1 什么是 RPZ
RPZ 是一种特殊的 DNS 区域文件,用于定义查询策略。当递归服务器收到查询时,会先检查 RPZ 规则,根据规则决定是否修改响应。
正常流程:
客户端 → 递归服务器 → 权威服务器 → 返回真实 IP
RPZ 流程:
客户端 → 递归服务器 → 检查 RPZ 规则
→ 命中规则 → 返回拦截响应
→ 未命中 → 继续正常解析
10.1.2 RPZ 的用途
| 用途 | 说明 | 示例 |
|---|
| 恶意软件拦截 | 阻断 C2 通信 | malware.example.com |
| 钓鱼防护 | 阻止访问钓鱼网站 | phishing-site.com |
| 广告过滤 | 屏蔽广告域名 | ads.example.com |
| 合规管控 | 阻止访问特定网站 | gambling-site.com |
| 内部策略 | 重定向特定域名 | social-media.com |
10.1.3 RPZ 响应类型
| 响应类型 | DNS 响应 | 客户端行为 |
|---|
| NXDOMAIN | 域名不存在 | 浏览器显示错误 |
| NODATA | 无记录 | 不显示错误,但无法连接 |
| CNAME 重定向 | 指向其他域名 | 访问重定向目标 |
| 丢弃(DROP) | 不响应 | 连接超时 |
| 记录修改 | 返回自定义 IP | 连接到指定服务器 |
10.2 配置 RPZ
10.2.1 基本配置
// named.conf
options {
recursion yes;
allow-recursion { trusted; };
// 启用 RPZ
response-policy {
zone "rpz.example.com" policy nxdomain;
// 可以有多个 RPZ 区域,按顺序匹配
// zone "rpz-ads.example.com" policy nxdomain;
};
};
// RPZ 区域定义
zone "rpz.example.com" {
type primary;
file "primary/rpz.example.com.zone";
allow-query { none; }; // 不允许外部查询 RPZ 区域
allow-transfer { none; }; // 不允许传输
};
10.2.2 RPZ 区域文件
; primary/rpz.example.com.zone
; 恶意域名拦截策略区域
$TTL 60
$ORIGIN rpz.example.com.
@ IN SOA ns1.example.com. admin.example.com. (
2026051001 ; Serial
3600 ; Refresh
900 ; Retry
1209600 ; Expire
60 ; Minimum (短 TTL)
)
IN NS localhost.
; ---- 恶意域名拦截(返回 NXDOMAIN) ----
malware-c2.example.com IN CNAME . ; NXDOMAIN
phishing-site.com IN CNAME . ; NXDOMAIN
evil-domain.net IN CNAME . ; NXDOMAIN
cryptominer.pool.com IN CNAME . ; NXDOMAIN
; ---- 广告域名拦截 ----
ads.example.com IN CNAME .
tracker.analytics.com IN CNAME .
ad.doubleclick.net IN CNAME .
; ---- 重定向到安全页面 ----
blocked.example.com IN A 192.168.1.250 ; 拦截页面
warning.example.com IN A 192.168.1.251 ; 警告页面
; ---- 通配符拦截 ----
*.malware-domain.com IN CNAME . ; 拦截所有子域名
*.tracking.example.net IN CNAME .
; ---- 白名单(覆盖 RPZ 规则) ----
; 如果某个域名被上游 RPZ 列表误拦截,可以放行
safe-malware.example.com IN CNAME rpz-passthru. ; 放行
; ---- 丢弃响应(客户端看到超时) ----
slowloris.example.com IN CNAME rpz-drop. ; 丢弃
; ---- 自定义响应 ----
custom.example.com IN TXT "Blocked by policy" ; 返回 TXT
10.2.3 RPZ 特殊记录
| 特殊记录 | 作用 |
|---|
CNAME . | 返回 NXDOMAIN(域名不存在) |
CNAME *. | 返回 NODATA(域名存在但无记录) |
CNAME rpz-passthru. | 放行(白名单) |
CNAME rpz-drop. | 丢弃查询(不响应) |
CNAME rpz-tcp-only. | 仅允许 TCP 查询 |
CNAME target.example.com. | 重定向到目标域名 |
10.3 使用第三方 RPZ 列表
10.3.1 常见 RPZ 数据源
10.3.2 自动更新 RPZ 列表
#!/bin/bash
# /opt/scripts/update-rpz.sh
# 自动下载和更新 RPZ 列表
RPZ_DIR="/var/cache/bind/primary"
RPZ_FILE="${RPZ_DIR}/rpz.example.com.zone"
BACKUP_DIR="/var/backups/rpz"
DATE=$(date +%Y%m%d%H%M%S)
# 创建备份
mkdir -p "$BACKUP_DIR"
cp "$RPZ_FILE" "${BACKUP_DIR}/rpz-${DATE}.zone"
# 生成新的 RPZ 区域文件
cat > "$RPZ_FILE" <<HEADER
\$TTL 60
\$ORIGIN rpz.example.com.
@ IN SOA ns1.example.com. admin.example.com. (
${DATE} ; Serial
3600 ; Refresh
900 ; Retry
1209600 ; Expire
60 ; Minimum
)
IN NS localhost.
HEADER
# 下载恶意域名列表
curl -s "https://hole.cert.pl/domains/domains.txt" | while read domain; do
# 跳过注释和空行
[[ "$domain" =~ ^#.*$ || -z "$domain" ]] && continue
echo "${domain}. IN CNAME ." >> "$RPZ_FILE"
done
# 下载广告域名列表
curl -s "https://some-adblock-list/ads.txt" | while read domain; do
[[ "$domain" =~ ^#.*$ || -z "$domain" ]] && continue
echo "${domain}. IN CNAME ." >> "$RPZ_FILE"
done
# 添加自定义拦截
cat >> "$RPZ_FILE" <<CUSTOM
; 自定义拦截
custom-block.com. IN CNAME .
CUSTOM
# 检查语法
/usr/sbin/named-checkzone rpz.example.com "$RPZ_FILE"
if [ $? -eq 0 ]; then
# 重载区域
/usr/sbin/rndc reload rpz.example.com
echo "RPZ updated: $(wc -l < "$RPZ_FILE") rules"
else
echo "RPZ syntax error, reverting"
cp "${BACKUP_DIR}/rpz-${DATE}.zone" "$RPZ_FILE"
fi
# 清理旧备份(保留 30 天)
find "$BACKUP_DIR" -name "rpz-*.zone" -mtime +30 -delete
10.3.3 定时任务
# 添加到 crontab
sudo crontab -e
# 每天凌晨 3 点更新
0 3 * * * /opt/scripts/update-rpz.sh >> /var/log/rpz-update.log 2>&1
10.4 多 RPZ 区域策略
10.4.1 多区域配置
options {
response-policy {
zone "rpz-custom.example.com" policy nxdomain; // 自定义列表
zone "rpz-malware.example.com" policy nxdomain; // 恶意软件
zone "rpz-phishing.example.com" policy nxdomain; // 钓鱼网站
zone "rpz-ads.example.com" policy nxdomain; // 广告
zone "rpz-whitelist.example.com" policy passthru; // 白名单(最高优先级)
} qname-wait-recurse no;
};
优先级:列表中的顺序很重要,第一个匹配的规则生效。白名单应放在最后(或单独使用 policy passthru)。
10.4.2 按客户端应用不同策略
// 结合视图使用
view "strict" {
match-clients { 192.168.1.0/24; }; // 严格管控子网
options {
response-policy {
zone "rpz-strict.example.com" policy nxdomain;
};
};
zone "rpz-strict.example.com" {
type primary;
file "primary/rpz-strict.example.com.zone";
};
};
view "relaxed" {
match-clients { 192.168.2.0/24; }; // 宽松子网
options {
response-policy {
zone "rpz-relaxed.example.com" policy nxdomain;
};
};
zone "rpz-relaxed.example.com" {
type primary;
file "primary/rpz-relaxed.example.com.zone";
};
};
10.5 RPZ 日志与审计
10.5.1 启用 RPZ 日志
logging {
channel rpz_log {
file "/var/log/named/rpz.log" versions 10 size 100m;
severity info;
print-time yes;
print-severity yes;
print-category yes;
};
// RPZ 触发时记录
category rpz { rpz_log; };
};
10.5.2 日志格式
# 典型 RPZ 日志条目
10-May-2026 14:30:15.123 rpz: info: client @0x7f8b8c0d 192.168.1.100#12345: \
rpz QNAME NXDOMAIN rewrite <malware-c2.example.com/A/NXDOMAIN> \
via rpz.example.com
| 字段 | 说明 |
|---|
| 时间戳 | 查询时间 |
| 客户端 IP | 发起查询的客户端 |
| 原始查询 | 被拦截的域名 |
| 拦截动作 | NXDOMAIN / NODATA / 重定向 |
| 触发的 RPZ 区域 | 哪个 RPZ 规则生效 |
10.5.3 统计信息
# 查看 RPZ 统计
rndc stats
cat /var/cache/bind/named.stats
# 输出中会包含 RPZ 相关统计
# rpz: nxdomain 1234
# rpz: nodata 56
# rpz: passthru 78
# rpz: drop 12
10.6 RPZ 性能优化
10.6.1 性能影响
| RPZ 规模 | 性能影响 | 建议 |
|---|
| < 10,000 条 | 可忽略 | 标准配置 |
| 10,000 - 100,000 条 | 轻微 | 增加内存 |
| > 100,000 条 | 明显 | 使用专用服务器 |
10.6.2 优化配置
options {
response-policy {
zone "rpz.example.com" policy nxdomain;
}
// 性能优化选项
qname-wait-recurse no; // 不等待递归完成(推荐)
max-policy-ttl 300; // 策略最大 TTL(秒)
min-ns-dots 0; // 最少点数才触发 RPZ
break-dnssec yes; // 允许 RPZ 覆盖 DNSSEC(需要)
};
| 选项 | 默认值 | 说明 |
|---|
qname-wait-recurse | yes | 是否等待递归解析完成 |
max-policy-ttl | - | 策略响应的最大 TTL |
break-dnssec | no | 是否允许 RPZ 覆盖 DNSSEC 签名 |
10.7 业务场景
10.7.1 企业网络安全
// 场景:企业部署 RPZ 阻断恶意软件通信
zone "rpz-corporate.example.com" {
type primary;
file "primary/rpz-corporate.zone";
allow-update { key rpz-update-key; }; // 允许安全团队更新
};
10.7.2 公共 Wi-Fi
// 场景:咖啡店 Wi-Fi 拦截恶意和成人内容
options {
response-policy {
zone "rpz-public-wifi.example.com" policy nxdomain;
};
};
10.7.3 学校网络
// 场景:学校网络过滤不适宜内容
options {
response-policy {
zone "rpz-school.example.com" policy nxdomain; // 不适宜内容
zone "rpz-educational.example.com" policy passthru; // 教育资源白名单
};
};
10.8 本章小结
| 配置项 | 说明 | 推荐值 |
|---|
| RPZ 区域类型 | type primary | 使用本地文件或动态更新 |
| 默认策略 | policy nxdomain | 最安全 |
| 白名单 | CNAME rpz-passthru. | 覆盖拦截规则 |
| 日志 | category rpz | 监控拦截情况 |
| 更新频率 | 每天 | 自动化脚本 |
💡 小技巧
- RPZ 区域 TTL 设短:60 秒,便于快速更新策略。
- 不要暴露 RPZ 区域:
allow-query { none; }; 防止外部查询。 - 使用
qname-wait-recurse no:提升性能。 - 白名单放在最后:确保白名单覆盖其他规则。
- 定期备份 RPZ 数据:防止误删规则。
📖 扩展阅读