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

BIND DNS 服务器搭建完全教程 / 第 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 数据源

来源 URL 类型
SURBL https://surbl.org/ 恶意域名
Spamhaus https://www.spamhaus.org/ 垃圾邮件/恶意软件
abuse.ch https://urlhaus.abuse.ch/ 恶意 URL
CERT.PL https://hole.cert.pl/ 恶意软件
自建列表 内部维护 企业定制

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 监控拦截情况
更新频率 每天 自动化脚本

💡 小技巧

  1. RPZ 区域 TTL 设短:60 秒,便于快速更新策略。
  2. 不要暴露 RPZ 区域allow-query { none; }; 防止外部查询。
  3. 使用 qname-wait-recurse no:提升性能。
  4. 白名单放在最后:确保白名单覆盖其他规则。
  5. 定期备份 RPZ 数据:防止误删规则。

📖 扩展阅读