Homas/ioc2rpz

GitHub: Homas/ioc2rpz

ioc2rpz 是一款用 Erlang 编写的专用 DNS 服务器,将威胁情报指标自动转换为 RPZ 响应策略区并分发给下游 DNS 服务器,实现 DNS 层面的恶意流量阻断。

Stars: 113 | Forks: 18

# ioc2rpz™ 让您的威胁情报变得可操作 [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Erlang/OTP](https://img.shields.io/badge/Erlang%2FOTP-24%2B-blue.svg)](https://www.erlang.org/) [![Docker Hub](https://img.shields.io/docker/pulls/pvmdel/ioc2rpz.svg)](https://hub.docker.com/r/pvmdel/ioc2rpz) ## 目录 - [简述](#short-summary) - [概述](#overview) - [ioc2rpz™:威胁情报与 DNS 的交汇点](#ioc2rpz-is-a-place-where-threat-intelligence-meets-dns) - [架构概述](#architecture-overview) - [如何使用 ioc2rpz™](#how-to-use-ioc2rpz) - [ioc2rpz™ Web 界面](#ioc2rpz-web-interface) - [协议支持](#protocol-support) - [端口摘要](#port-summary) - [UDP (端口 53)](#udp-port-53) - [TCP (端口 53)](#tcp-port-53) - [DNS over TLS / DoT (端口 853)](#dns-over-tls--dot-port-853) - [DNS over HTTPS / DoH (端口 443/8443)](#dns-over-https--doh-port-4438443) - [速率限制](#rate-limiting) - [DNS NOTIFY](#dns-notify) - [ioc2rpz™ 对比 ISC BIND 及其他 DNS](#ioc2rpz-vs-isc-bind-vs-other-dns) - [安装](#installation) - [Docker 容器](#docker-container) - [环境变量](#environment-variables) - [Docker Compose](#docker-compose) - [AWS 上的 ioc2rpz™](#ioc2rpz-on-aws) - [证书设置](#certificate-setup) - [从源码构建](#building-from-source) - [ioc2rpz™ 管理](#ioc2rpz-management) - [通过 DNS 管理](#via-dns) - [通过 REST 管理](#via-rest) - [监控与健康检查](#monitoring--health-checks) - [故障排除](#troubleshooting) - [配置文件](#configuration-file) - [预定义配置值](#predefined-configuration-values---includeioc2rpzhrl) - [AXFR 和 IXFR 缓存的更新方式](#how-the-axfr-full-and-ixfr-incremental-caches-are-updated) - [热缓存](#hot-cache) - [如何试用 ioc2rpz™](#how-to-try-ioc2rpz-or-sample-and-free-rpz-feeds-hosted-by-ioc2rpz) - [一些免费的威胁情报源](#some-free-threat-intelligence-feeds) - [更多文档](#further-documentation) - [参考文献](#references) - [支持者/捐助者](#do-you-want-to-support-to-the-project) - [联系我们](#contact-us) - [许可证](#license) ## 简述 ioc2rpz™:DNS 安全解决方案 - ioc2rpz™ 是一款功能强大的 DNS 服务器,可将威胁指标转化为可操作的响应策略区域 (RPZ) 数据源。它自动化了更新过程,确保您的网络免受包括恶意域名和 IP 地址在内的最新威胁。通过将 IOC 数据源转换为 RPZ,ioc2rpz™ 在威胁情报与 DNS 安全之间架起了关键桥梁,并兼容支持 RPZ 的 DNS 服务器(如 ISC BIND 或 PowerDNS)。 ## 概述 DNS 是互联网的控制平面。通常 DNS 被用于正当目的,但是: - 它可以被用来追踪用户位置及其行为; - 恶意软件利用 DNS 进行命令与控制、数据窃取或流量重定向; - 根据 2016 年思科年度安全报告,91.3% 的恶意软件使用了 DNS; - 广告公司通常使用独立且隐晦的域名来展示广告; - 免费 DNS 服务(例如 1.1.1.1、8.8.8.8、9.9.9.9 等)可以帮助您解决一些问题,但您无法定义自己的保护设置或广告过滤器。

ISC BIND 已成为域名服务器事实上的标准。随着 ISC BIND 9.8 引入响应策略区域,在 DNS 层面监控和遏制恶意软件变得十分简单。PowerDNS 递归服务器 4.0.0 及更高版本支持 RPZ。Knot DNS 也部分支持 RPZ。 与传统网络保护解决方案相比,DNS 服务器可以处理数以百万计的指标而不会影响性能,但以前一直没有自动化且高效的方法来维护主 DNS 服务器上的响应策略区域。 通常,失陷指标以纯文本形式分发,但格式各异,只有少数 IOC 提供商通过 RPZ 提供它们。 ioc2rpz™ 是一款自定义 DNS 服务器,可自动将来自各种源的指标(例如恶意 FQDN、IP)转换为 RPZ 数据源,并自动维护/更新它们。这些数据源可以分发到任何支持 RPZ 的开源和/或商业 DNS 服务器,例如 ISC BIND、PowerDNS。您可以在路由器、台式机、服务器甚至 Raspberry Pi 上运行带有 RPZ 过滤功能的自有 DNS 服务器。系统内存是唯一的限制。 使用 ioc2rpz™,您可以定义自己的数据源和操作,从而阻止不受欢迎的通信。 ## ioc2rpz™:威胁情报与 DNS 的交汇点 ioc2rpz™ 将 IOC 数据源转化为响应策略区域 (RPZ)。您可以混合多个数据源来生成单个 RPZ 或多个 RPZ。受信任的域名和 IP 可以被列入白名单。ioc2rpz™ 支持指标过期,并相应地重建区域。 ![Alt ioc2rpz™](https://github.com/Homas/ioc2rpz/blob/master/IOC2RPZ.jpg) 当前版本支持:本地文件、通过 http/https/ftp 获取文件/请求,以及用于访问其他资源类型的 shell 脚本。只要您能编写 REGEX 来提取指标,就可以使用任何文件格式,前提是指标之间通过换行符和/或回车符 (/n, /r, /r/n) 分隔。 ## 架构概述 ioc2rpz 基于 Erlang/OTP 构建,其监督树可确保容错性和自动恢复。详情请参见 [docs/architecture.md](docs/architecture.md)。 ``` ioc2rpz_app (application) └── ioc2rpz_sup (supervisor) ├── ioc2rpz_db_sup — ETS table heir process ├── ioc2rpz_tcp_sup — TCP listener pool (5 workers) ├── ioc2rpz_udp_sup — UDP listener ├── ioc2rpz_tls_sup — TLS/DoT listener pool (5 workers) [if cert configured] └── ioc2rpz_rest_sup — Cowboy HTTPS (REST API + DoH) [if cert configured] ``` 核心模块: | 模块 | 职责 | |--------|---------------| | `ioc2rpz.erl` | TCP/TLS DNS worker — 接受、解析、验证、响应 | | `ioc2rpz_udp.erl` | UDP DNS 监听器 — SOA 查询 | | `ioc2rpz_conn.erl` | IOC 源获取 (HTTP/HTTPS/file/shell) | | `ioc2rpz_db.erl` | 基于 ETS 的区域和数据包缓存 | | `ioc2rpz_sup.erl` | 主监督者,配置加载,区域调度 | | `ioc2rpz_rest.erl` | REST 管理 API (Cowboy) | | `ioc2rpz_doh.erl` | DNS-over-HTTPS 处理程序 | ## 如何使用 ioc2rpz™ 您可以将 ioc2rpz™ 与任何支持响应策略区域的 DNS 服务器结合使用,例如最新版本的 ISC BIND、PowerDNS 以及任何基于这些产品的商业 DNS 服务器(例如 Infoblox、Blue Cat、Efficient IP)。cfg 文件夹中提供了一个 BIND 示例配置文件。

## ioc2rpz™ Web 界面 [ioc2rpz.gui](https://github.com/Homas/ioc2rpz.gui) 是作为独立项目开发的管理 Web 界面。它不是运行 ioc2rpz™ 的必需组件。 ## 协议支持 ioc2rpz™ 监听多种传输协议。所有传输方式共享相同的查询处理管道:速率限制、TSIG 验证、区域查找和响应生成。完整协议文档请参见 [docs/protocols.md](docs/protocols.md)。 ### 端口摘要 | 端口 | 协议 | 服务 | 条件 | |------|----------|---------|-----------| | 53 | UDP | DNS 查询 (仅 SOA) | 始终 | | 53 | TCP | DNS 查询、AXFR/IXFR 区域传送、管理 | 始终 | | 853 | TCP+TLS | DoT — 与 TCP 相同但经过加密 | 需要 `cert` 配置 | | 443/8443 | TCP+TLS | DoH (`/dns-query`) 和 REST API | 需要 `cert` 配置 | ### UDP (端口 53) UDP 用于轻量级 DNS 查询,主要是 SOA 查找。超过 512 字节(或 EDNS0 通告的缓冲区大小)的响应将根据 RFC 1035 §4.2.1 设置 TC (截断) 位,提示客户端通过 TCP 重试。UDP 不支持管理命令。 ``` dig @127.0.0.1 zone.ioc2rpz SOA -y hmac-sha256:keyname:base64key ``` ### TCP (端口 53) TCP 处理区域传送 (AXFR/IXFR)、SOA 查询和管理命令。由包含 5 个预创建接受 worker 的连接池负责处理传入连接。 ``` # AXFR 区域传送 dig @127.0.0.1 zone.ioc2rpz AXFR +tcp -y hmac-sha256:keyname:base64key # IXFR 增量传送 dig @127.0.0.1 zone.ioc2rpz IXFR=12345 +tcp -y hmac-sha256:keyname:base64key ``` ### DNS over TLS / DoT (端口 853) ioc2rpz™ 支持通过 DoT 分发 RPZ。当配置中存在 `cert` 记录时,TLS 监听器会在端口 853 上自动启动。DoT 支持与 TCP 相同的操作 (AXFR、IXFR、SOA、管理)。 - 支持的 TLS 版本:1.2 和 1.3 (`?TLSVersion = 'tlsv1.2-1.3'`) - 根据 RFC 7858 §3.4 支持连接重用(每次 TLS 会话允许多个查询,30 秒空闲超时) - 不支持 TLS PIN - DNS NOTIFY 消息以未加密形式发送(明文 UDP) - 磁盘上的证书文件被替换时会自动刷新(由于 Erlang SSL 缓存,最多约有 2 分钟延迟) 有关证书设置,请参见[证书设置](#certificate-setup)。 ``` # 基于 DoT 的 SOA 查询 kdig @127.0.0.1 -p 853 zone.ioc2rpz SOA +tls -y hmac-sha256:keyname:base64key # 基于 DoT 的 AXFR dig @127.0.0.1 -p 853 zone.ioc2rpz AXFR +tls +tcp -y hmac-sha256:keyname:base64key ``` ### DNS over HTTPS / DoH (端口 443/8443) DoH 通过 `/dns-query` 端点经由 HTTPS 提供 DNS 解析。支持的方法: - **GET**:在 `?dns=` 查询参数中使用 base64url 编码的 DNS 消息 - **POST**:使用 `Content-Type: application/dns-message` 请求体(最大 4096 字节;更大的负载将收到 HTTP 413 错误) 响应使用 `Content-Type: application/dns-message`。DoH 查询受限于基于 IP 的 ACL 强制执行,该 ACL 使用 `srv` 记录中的配置。 ``` # DoH GET 请求 curl -H "Accept: application/dns-message" \ "https://127.0.0.1:443/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB" -k # DoH POST 请求 curl -X POST -H "Content-Type: application/dns-message" \ --data-binary @dns_query.bin "https://127.0.0.1:443/dns-query" -k ``` ### 速率限制 DNS 查询按客户端 IP 地址进行速率限制。当超过限制时,服务器将返回 DNS `REFUSED` 响应。 | 参数 | 默认值 | 宏 | |-----------|---------|-------| | 窗口期 | 10 秒 | `?RATE_LIMIT_WINDOW` (10000 ms) | | 每个窗口期的最大请求数 | 1 | `?MAX_REQUESTS_PER_WINDOW` | 速率限制适用于所有 DNS 查询传输 (UDP、TCP、TLS、DoH)。窗口期和阈值可通过 `include/ioc2rpz.hrl` 中的宏进行配置。 ### DNS NOTIFY 在区域更新 (AXFR 或 IXFR) 后,ioc2rpz™ 会通过 UDP 向配置在 RPZ `NotifyList` 中的 IP 地址发送 DNS NOTIFY 消息 ([RFC 1996](https://tools.ietf.org/html/rfc1996))。这会提示辅助 DNS 服务器检查区域 SOA 序列号,如果序列号发生更改,则发起传送。 ``` %% NotifyList in RPZ config — last field before whitelists {rpz, {"zone.ioc2rpz", ..., ["source1"], ["10.0.0.1", "10.0.0.2"], []}}. ``` ## ioc2rpz™ 对比 ISC BIND 及其他 DNS - ioc2rpz™ 专为处理 RPZ 分发而构建; - ioc2rpz™ 支持 DoT (DNS over TLS),因此无人能轻易窃听您的 RPZ/指标; - ioc2rpz™ 支持面向现代 DNS 客户端的 DoH (DNS over HTTPS); - ioc2rpz™ 支持您所需的任意数量的 RPZ; - ioc2rpz™ 支持实时/非缓存区域。它根据传入请求创建区域; - 可以通过不同协议从不同来源拉取指标(例如通过 REST API 调用); - RPZ 会自动更新; - IOC 过期时间用于及时移除过期指标; - 具备性能优化以及区域传送时间/大小/数据包优化。 ## 安装 部署该服务最简单的方法是使用 Docker Hub 上的 Docker 容器。您可以在 ioc2rpz™ wiki 中找到 [Docker 部署教程](https://github.com/Homas/ioc2rpz/wiki/Deployment-on-Docker)。 ## Docker 容器 ioc2rpz™ 可在 Docker Hub 上获取。直接搜索 ioc2rpz™ 即可。 前提条件: - ioc2rpz™ 不包含配置文件,您需要将 /opt/ioc2rpz/cfg 挂载到主机系统上包含配置文件 的目录; - ioc2rpz™ 使用 53/udp(仅 SOA 请求)、53/tcp(AXFR、FR、SOA、MGMT)、853/tcp(AXFR、IXFR、SOA、MGMT)和 8443/tcp(REST API、DoH)端口。这些端口应暴露给主机系统; - ioc2rpz™ 会将 ETS 数据库保存到文件中以加快启动速度。您可以将 /opt/ioc2rpz/db 挂载到主机系统上的某个目录,以便在重启后保留数据库; 您可以使用以下命令启动 ioc2rpz™: ``` sudo docker run -d --name ioc2rpz --log-driver=syslog --restart always --mount type=bind,source=/home/ioc2rpz/cfg,target=/opt/ioc2rpz/cfg --mount type=bind,source=/home/ioc2rpz/db,target=/opt/ioc2rpz/db -p53:53 -p53:53/udp -p853:853 -p8443:8443 pvmdel/ioc2rpz ``` 其中 /home/ioc2rpz/cfg、/home/ioc2rpz/db 是主机系统上的目录。 您可以通过 ``-e`` 参数传递自定义配置文件名。例如:``-e CONF=./cfg/ioc2rpz2.conf`` ## 环境变量 ioc2rpz™ 使用以下环境变量,主要与 Docker 部署相关。它们定义在 `config/sys.config.src` 和 `config/vm.args` 中。 | 变量 | 默认值 | 描述 | |----------|---------|-------------| | `IPv4` | — | IPv4 绑定地址 | | `IPv6` | — | IPv6 绑定地址 | | `CONF` | — | 配置文件路径(例如 `./cfg/ioc2rpz.conf`) | | `DB` | `/opt/ioc2rpz/db` | ETS 持久化的数据库目录 | | `CD` | `/opt/ioc2rpz` | 工作目录 | | `NODE_NAME` | `ioc2rpz` | Erlang 节点短名称 | | `IO2Cookie` | `ioc2rpz` | Erlang 分布式 Cookie | 使用 `-e` 将环境变量传递给 Docker: ``` docker run -d --name ioc2rpz -e CONF=./cfg/custom.conf -e NODE_NAME=mynode ... ``` ## Docker Compose 您可以使用 Docker Compose 部署 ioc2rpz™ 和 ioc2rpz.gui。规范的 docker-compose.yml 文件可以在 [ioc2rpz.dc](https://github.com/Homas/ioc2rpz.dc) 仓库中找到。 以下是一个示例 `docker-compose.yml`,展示了带有 Web UI 和 Let's Encrypt certbot 搭配进程的 ioc2rpz: ``` version: "3.8" services: ioc2rpz: image: pvmdel/ioc2rpz container_name: ioc2rpz restart: always logging: driver: syslog ports: - "53:53/tcp" - "53:53/udp" - "853:853/tcp" - "8443:8443/tcp" volumes: - ./cfg:/opt/ioc2rpz/cfg - ./db:/opt/ioc2rpz/db - letsencrypt-certs:/opt/ioc2rpz/ssl:ro ioc2rpz-gui: image: pvmdel/ioc2rpz.gui container_name: ioc2rpz-gui restart: always ports: - "443:443" depends_on: - ioc2rpz certbot: image: certbot/certbot container_name: certbot volumes: - letsencrypt-certs:/etc/letsencrypt - letsencrypt-www:/var/www/certbot entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet; sleep 12h; done'" volumes: letsencrypt-certs: letsencrypt-www: ``` 更新您的 `ioc2rpz.conf` 以引用挂载的证书路径: ``` {cert, {"ssl/live/ns1.rpz-proxy.com/fullchain.pem", "ssl/live/ns1.rpz-proxy.com/privkey.pem", ""}}. ``` ## AWS 上的 ioc2rpz™ 您可以在 AWS 上运行 ioc2rpz™ 和 ioc2rpz.gui。对于相对较小的部署(数十万个指标),即使是免费套餐也足够了。 下面的视频展示了如何使用 ECS 在 AWS 上设置 ioc2rpz™ 和 ioc2rpz.gui。

## 证书设置 DoT(端口 853)、REST API(端口 8443)和 DoH 都需要 TLS 证书。所有 TLS 服务共用同一份证书。详情请参见 [docs/deployment.md](docs/deployment.md)。 ### 自签名证书(开发环境) ``` openssl req -x509 -newkey rsa:2048 -keyout cfg/ioc2rpz_dot.key \ -out cfg/ioc2rpz_dot.crt -days 365 -nodes -subj "/CN=ioc2rpz" ``` ### Let's Encrypt(生产环境) ``` # 获取证书 sudo certbot certonly --standalone -d ns1.rpz-proxy.com # 复制到 ioc2rpz cfg 目录 cp /etc/letsencrypt/live/ns1.rpz-proxy.com/fullchain.pem cfg/ioc2rpz_dot.crt cp /etc/letsencrypt/live/ns1.rpz-proxy.com/privkey.pem cfg/ioc2rpz_dot.key ``` ### 自动续期 ``` # /etc/cron.d/ioc2rpz-cert-renew 0 3 * * * root certbot renew --quiet --deploy-hook "cp /etc/letsencrypt/live/ns1.rpz-proxy.com/fullchain.pem /opt/ioc2rpz/cfg/ioc2rpz_dot.crt && cp /etc/letsencrypt/live/ns1.rpz-proxy.com/privkey.pem /opt/ioc2rpz/cfg/ioc2rpz_dot.key" ``` ### Docker 卷挂载 在 Docker 中运行时,从主机挂载证书目录: ``` docker run -d --name ioc2rpz \ --mount type=bind,source=/etc/letsencrypt/live/ns1.rpz-proxy.com,target=/opt/ioc2rpz/ssl,readonly \ ... ``` 在 `ioc2rpz.conf` 中引用: ``` {cert, {"ssl/fullchain.pem", "ssl/privkey.pem", ""}}. ``` Erlang 会在约 2 分钟内自动获取已替换的证书文件。在配置重载(`ioc2rpz-reload-cfg`)期间也会显式重新加载证书。切勿让证书过期——为确保服务不中断,请在过期前进行续期。 ## 从源码构建 默认情况下,ioc2rpz™ 从 ./cfg/ioc2rpz.conf 读取配置,监听所有网络接口,并将数据库备份保存在 ./db 目录中。您可以在 ``include/ioc2rpz.hrl`` 中更改默认值。 如果您下载了源码,在运行 ioc2rpz™ 之前,您必须使用以下命令编译代码:``rebar3 release``。 您可以通过调用 ``_build/default/rel/ioc2rpz/bin/ioc2rpz start`` 来启动应用程序。 ## ioc2rpz™ 管理 ### 通过 DNS 管理 ioc2rpz™ 支持通过 DNS/TCP 或 DoT 进行管理。建议使用 DoT 或 REST API 而不是 DNS/TCP。当前版本的 ioc2rpz™ 不支持单独的管理 IP/接口。无论如何,强烈建议创建一个专用的 TSIG 密钥(或多个密钥)仅用于管理。您可以关闭通过 DNS 进行管理的功能。 支持的操作: - ioc2rpz™ 当前状态。请求 ``ioc2rpz-status``,类别 ``CHAOS``,记录类型 ``TXT``。例如: ``` dig +tcp -y dnsmkey_1:ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA== @127.0.0.1 ioc2rpz-status TXT -c CHAOS ``` - 重新加载配置文件。RR 名称 ``ioc2rpz-reload-cfg``,RR 类别 ``CHAOS``,RR 类型 ``TXT`` - 更新 TSIG 密钥。RR 名称 ``ioc2rpz-update-tkeys``,RR 类别 ``CHAOS``,RR 类型 ``TXT`` - 刷新所有区域。RR 名称 ``ioc2rpz-update-all-rpz``,RR 类别 ``CHAOS``,RR 类型 ``TXT`` - 刷新某个区域。RR 名称 ``zone_name``,RR 类别 ``CHAOS``,RR 类型 ``TXT``。例如,可以通过以下命令调用以完全刷新 ``dga.ioc2rpz``: ``` dig +tcp -y dnsmkey_1:ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA== @127.0.0.1 dga.ioc2rpz TXT -c CHAOS ``` - 停止 ioc2rpz™。RR 名称 ``ioc2rpz-terminate``,RR 类别 ``CHAOS``,RR 类型 ``TXT`` - 请求示例区域。RR 名称 ``sample-zone.ioc2rpz``,RR 类别 ``IN``,RR 类型 ``AXFR`` ### 通过 REST 管理 REST API(端口 8443/tcp)是首选的管理接口。出于安全原因,所有管理流量必须加密,如果没有 SSL 证书,REST API 将不会启动。所有端点均支持 GET 和 POST 方法。 使用 HTTP 基本认证对请求进行身份验证。管理 TSIG 密钥用于请求认证。TSIG 密钥名称被用作 HTTP 用户名,TSIG 密钥作为密码。对 REST API 的访问受限于 `srv` 记录中定义的 ACL。 API 版本段同时支持 `v1` 和 `v1.0`(例如,`/api/v1/stats/serv` 或 `/api/v1.0/stats/serv`)。 REST API 根据 `Accept` 请求头支持 JSON(默认)和纯文本输出: - `application/json` — JSON 输出(默认) - `text/plain` — 纯文本输出 ``` # 示例:纯文本输出 curl -u "keyname:base64key==" -k -H "Accept: text/plain" https://127.0.0.1:8443/api/v1/mgmt/update_tkeys ``` 文本响应使用以下格式: ``` status: ok msg: TSIG keys were updated ``` #### 路径参数 | 参数 | 描述 | |-----------|-------------| | `:rpz_name` | RPZ 区域名称(例如 `dga.ioc2rpz`) | | `:source_name` | IOC 来源名称(例如 `sample_fqdn`) | | `:ioc` | 要查找的指标(FQDN 或 IP,例如 `baddomain.com`) | #### 统计端点 `/api/v1/stats/serv` — 服务器统计信息(节点名称、总规则数、内存使用情况) ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/stats/serv ``` ``` { "srv": { "node_name": "ioc2rpz@hostname", "srv_total_rules": 15000, "hot_cache_mem": "12.5 Mb", "axfr_table_mem": "45.2 Mb", "ixfr_table_mem": "8.1 Mb" }, "rpz": [...], "sources": [...] } ``` `/api/v1/stats/rpz` — RPZ 区域统计信息 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/stats/rpz ``` ``` { "rpz": [ { "name": "malware.ioc2rpz", "rule_count": 5000, "ioc_count": 4500, "serial": 1709000000, "serial_ixfr": 1708990000, "update_time": 1709000000, "ixfr_update_time": 1708995000, "ixfr_nz_update_time": 1708995000 } ] } ``` `/api/v1/stats/source` — 来源统计信息 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/stats/source ``` ``` { "sources": [ {"name": "sample_fqdn", "ioc_count": 150} ] } ``` #### 管理端点 `/api/v1/mgmt/reload_cfg` — 重新加载配置文件 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/mgmt/reload_cfg ``` 成功:`{"status":"ok","msg":"Configuration reloaded"}` 失败 (HTTP 520):`{"status":"error","msg":"Configuration reload error"}` `/api/v1/mgmt/update_tkeys` — 从配置中重新加载 TSIG 密钥 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/mgmt/update_tkeys ``` 成功:`{"status":"ok","msg":"TSIG keys were updated"}` 失败 (HTTP 520):`{"status":"error","msg":"TSIG keys update error"}` `/api/v1/mgmt/terminate` — 优雅停止服务器 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/mgmt/terminate ``` 成功:`{"status":"ok","msg":"Terminating"}` #### 区域更新端点 `/api/v1/update/all_rpz` — 强制完全刷新所有 RPZ 区域 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/update/all_rpz ``` 成功:`{"status":"ok","msg":"All RPZ zones will be updated"}` `/api/v1/update/:rpz_name` — 强制完全刷新特定区域 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/update/dga.ioc2rpz ``` 成功:`{"status":"ok","msg":"RPZ dga.ioc2rpz will be updated"}` 失败 (HTTP 520):`{"status":"error","msg":"RPZ dga.ioc2rpz not found"}` #### 缓存管理端点 `/api/v1/cache/sources/clear/all` — 从热缓存中移除所有源 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/cache/sources/clear/all ``` 成功:`{"status":"ok","msg":"All sources were removed from the hotcache"}` `/api/v1/cache/sources/clear/:source_name` — 从热缓存中移除特定源 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/cache/sources/clear/sample_fqdn ``` 成功:`{"status":"ok","msg":"sample_fqdn source was removed from the hot cache"}` `/api/v1/cache/sources/load/all` — 将所有源重新加载到热缓存中 ``` curl -u "keyname:base64key==" -k https://127.0.0.1:8443/api/v1/cache/sources/load/all ``` 成功:`{"status":"ok","msg":"All sources will loaded to the hot cache"}` #### 数据源与 IOC 查询端点 `/api/v1/feed/:rpz_name` — 从 RPZ 数据源获取指标 查询参数:`?type=fqdn|ip|both`(默认:`both`) ``` curl -u "keyname:base64key==" -k "https://127.0.0.1:8443/api/v1/feed/malware.ioc2rpz?type=fqdn" ``` 成功: ``` { "status": "ok", "rpz": "malware.ioc2rpz", "iocs": ["baddomain.com", "evil.example.org"] } ``` 失败 (HTTP 520):`{"status":"error","msg":"RPZ malware.ioc2rpz not found"}` `/api/v1/ioc/:ioc` — 检查某个指标是否被任何 RPZ 数据源拦截 查询参数:`?tkey=keyname` — 将搜索范围限制在该密钥可访问的区域(可选) ``` curl -u "keyname:base64key==" -k "https://127.0.0.1:8443/api/v1/ioc/baddomain.com?tkey=dnsproxykey_1" ``` 成功: ``` { "ioc": "baddomain.com", "tkey": "dnsproxykey_1", "data": [ { "ioc": "baddomain.com", "feeds": [ { "feed": "malware.ioc2rpz", "wildcard": "true", "type": "fqdn", "rpz_serial": 1709000000, "ioc_expiration": 0 } ] } ] } ``` 失败:`{"status":"error", "ioc": "nonexistent.com"}` #### 不支持的端点 任何无法识别的路径将返回 HTTP 200 状态码及以下内容: ``` {"status":"error","msg":"Unsupported request"} ``` ## 监控与健康检查 ### REST API 状态 ``` # 服务器统计信息 curl -u "keyname:key==" -k https://127.0.0.1:8443/api/v1/stats/serv # RPZ zone 统计信息(指标数量、序列号、更新时间) curl -u "keyname:key==" -k https://127.0.0.1:8443/api/v1/stats/rpz # 来源统计信息 curl -u "keyname:key==" -k https://127.0.0.1:8443/api/v1/stats/source ``` ### Erlang Shell 检查 如果在交互式 shell 中运行或连接到正在运行的节点: ``` %% Check supervisor children supervisor:which_children(ioc2rpz_sup). supervisor:count_children(ioc2rpz_tls_sup_v6). supervisor:count_children(ioc2rpz_tcp_sup_v6). %% Check ETS table sizes (memory usage) ets:info(cfg_table, size). ets:info(rpz_hotcache_table, size). ets:info(rate_limits, size). ``` ### DNS 健康检查 ``` # 基于 UDP 的 SOA 查询 dig @localhost -p 53 your-zone.rpz SOA +short # 基于 TCP 的 Zone 传送 dig @localhost -p 53 your-zone.rpz AXFR +tcp -y hmac-sha256:keyname:base64key # DoT 查询 dig @localhost -p 853 +tls your-zone.rpz SOA # 示例 zone(内置测试 zone) dig @localhost sample-zone.ioc2rpz AXFR +tcp ``` 有关完整的监控和日志参考,请参见 [docs/deployment.md](docs/deployment.md)。 ## 故障排除 | 问题 | 解决方案 | |-------|----------| | **端口已被占用** | 使用 `lsof -i :53` / `lsof -i :853` 检查。监听套接字上设置了 `{reuseaddr, true}` 以便快速重启。 | | **DoT 无法接受连接** | 确认已配置 `{cert, ...}`。使用以下命令检查 TLS worker:`supervisor:count_children(ioc2rpz_tls_sup_v6).` 并检查端口 853 是否被防火墙拦截。 | | **区域传送失败(TSIG 不匹配)** | 验证客户端和服务器之间的密钥名称和密钥值是否匹配。在日志中查找 CEF 104/105 事件。 | | **源下载失败** | 检查网络连接。在日志中查找 `Error downloading feed`。服务器会重试 3 次,每次间隔 3 秒。对于 HTTPS 源,请确保具有有效的 TLS 证书。 | | **内存使用率过高** | 在 Erlang shell 中检查 ETS 表大小。`rate_limits` 和 `rpz_hotcache_table` 会被定期清理。考虑减小 `?HotCacheTime` 的值。 | 详细的故障排除方法请参见 [docs/deployment.md](docs/deployment.md)。 ## 配置文件 该配置是一个 Erlang 文件。每个配置选项都是一个 Erlang 项,因此配置必须符合 Erlang 语法。服务器在加载/重新加载时会验证配置项:TSIG 密钥编码、证书文件是否存在、正则表达式编译以及 URL 语法。无效的项会被记录并跳过。完整的配置参考请参见 [docs/configuration.md](docs/configuration.md)。 ioc2rpz™ 支持以下配置参数: - 单个 **srv** 记录(必填); - 单个 **cert** 记录(可选); - 零个或多个 **key** 记录(可选); - 零个或多个 **whitelist** 记录(可选); - 一个或多个 **source** 记录(至少需要一个源); - 一个或多个 **rpz** 记录(至少需要一个 rpz)。 ### **srv** 记录 **srv** 记录用于定义服务器的默认值。它包括: - SOA 记录中使用的 NS 服务器名称; - SOA 记录的电子邮件地址(采用 SOA 格式); - 管理 TS 密钥列表(仅名称)。详情请参阅[管理部分](#ioc2rpz-management)。 - 用于 REST API 和 DoH 访问控制的 ACL IP 地址列表。 **srv** 记录示例: ``` {srv,{"ns1.example.com","support.email.example.com",["dnsmkey_1","dnsmkey_2","dnsmkey_3"],["acl_ip1","acl_ip2"]}}. ``` ### **cert** 记录 **cert** 记录用于定义用于 DNS over TLS、REST API 和 DoH 通信的证书和私钥。有关证书生成和管理,请参见[证书设置](#certificate-setup)。 它包括: - 包含证书的文件路径; - 包含 PEM 编码私钥的文件路径; - 包含 PEM 编码 CA 证书的文件路径。 **cert** 记录示例: ``` {cert,{"cfg/cert.pem", "cfg/key.pem", "cfg/cacerts.pem"}}. ``` ### **include** 记录 **include** 记录允许将 ioc2rpz™ 配置拆分为多个文件。 **include** 记录示例: ``` {include,"cfg/tkeys.include.cfg"}. ``` ### **key** 记录 TSIG 密钥用于身份验证和授权。建议为 ioc2rpz™ 管理和区域传送使用不同的 TSIG 密钥。 **key** 记录包括: - TSIG 密钥名称; - 算法。支持 ``md5``、``sha256`` 和 ``sha512``; - 密钥; -(可选)它所属的密钥组列表。 **key** 记录示例: ``` {key,{"key_name_1","md5","ayVnL+h2QKMszRVohrngagcEuIpN3RkecXKdwSa5WsHD5N4Y5R3NUMGM W8sIGv36gPkAtWtgarqKzN9tmHqEnA=="}}. {key,{"key_name_2","sha256","5Yvt70eJnf95+LJeI8H3TgKGeVparmMB7udA0pv/JRE="}}. {key,{"key_name_3","sha512","03uuaGl9kqfenjRgIeCv6e29lVvMwviB1+cDX1I0jcVOcTU4jWFwRkfo3ULRMD+NGDfwzYvXkJ94FNEaAW4vzw==",["customers","public"]}}. ``` 可以使用 dnssec-keygen 工具生成 TSIG 密钥: ``` # MD5(512位) dnssec-keygen -a HMAC-MD5 -b 512 -n USER tsig-key # SHA-256(256位) dnssec-keygen -a HMAC-SHA256 -b 256 -n USER tsig-key # SHA-512(512位) dnssec-keygen -a HMAC-SHA512 -b 512 -n USER tsig-key ``` 详情请参阅 "dnssec-keygen" 文档。可以将密钥分配给组,以便在 RPZ 区域访问控制中进行基于组的授权。 ### **key_group** 记录 密钥组为区域传送和管理提供基于组的授权。您可以将密钥分配给命名组并引用该组,而不必在 `rpz` 或 `srv` 记录中逐个列出密钥。 有两种方法可以将密钥分配给组: 1. 通过 `key` 记录的可选第 4 个字段内联指定:`{key, {Name, Alg, Secret, [Groups]}}` 2. 通过 `key_group` 记录显式指定(如下所示) ``` {key_group, {GroupName, [KeyName1, KeyName2, ...]}}. ``` | 字段 | 类型 | 描述 | |-----------|-----------------|-------------| | GroupName | string | 组的名称(例如 `"customers"`) | | Keys | list of strings | 属于该组的 TSIG 密钥名称列表 | **key_group** 记录示例: ``` {key_group, {"customers", ["dnsproxykey_1", "dnsproxykey_2"]}}. {key_group, {"public", ["dnsproxykey_3"]}}. ``` 在 `rpz` 和 `srv` 记录中,可以使用密钥列表中的 `{groups, ["group1", "group2"]}` 元组来引用组: ``` {rpz, {"zone.ioc2rpz", 7202, 3600, 2592000, 7200, "true", "true", "nxdomain", ["dnsproxykey_1", {groups, ["customers", "public"]}], "fqdn", 86400, 3600, ["source1"], [], []}}. ``` ### **whitelist** 记录 白名单用于防止可能的错误并阻止受信任的域名和 IP 地址。列入白名单的 IOC 将从响应策略区域中移除。ioc2rpz™ 仅检查完全匹配,因此如果白名单 IP 地址包含在被阻止的子网中,它不会分割或丢弃该网络,反之亦然。白名单是一个文本文件或文本数据源。指标应由换行符(/n、/r 或 /n/r 两者)分隔。白名单必须包含有效的 FQDN 和/或 IP 地址。ioc2rpz™ 支持无限数量的指标。 **whitelist** 记录包括: - 白名单名称; - 白名单路径。支持 URL(http/https/ftp)和本地文件。前缀 "file:" 用于本地文件; - 用于提取指标的正则表达式。正则表达式必须包含在双引号中。如果指定空的正则表达式(`""`),将使用默认正则表达式(`"^([A-Za-z0-9][A-Za-z0-9\-\._]+)[^A-Za-z0-9\-\._]*.*$"`)。如果不需要正则表达式(源已经以所需格式提供数据),则使用 `none`。 **whitelist** 记录示例: ``` {whitelist,{"whitelist_1","file:cfg/whitelist1.txt",none}}. ``` ### **source** 记录 source 是恶意指标的数据源。支持 FQDN、IPv4 和 IPv6 地址。source 是一个文本文件或文本数据源。指标应由换行符/回车符(/n、/r 或 /r/n 两者)分隔。ioc2rpz™ 支持无限数量的指标。 **source** 记录包括: - 源名称; - 用于完整源传送 (AXFR) 的源路径。支持 URL(http/https/ftp)、本地文件和脚本。前缀 **file:** 用于本地文件。前缀 **shell:** 用于在主机/容器上执行应向 STDOUT 返回指标和可选过期时间的本地脚本/命令; - 用于增量源传送 (IXFR) 的源路径。AXFR、IXFR 路径支持使用关键字来缩短 URL 并提供区域更新时间戳: - **[:AXFR:]** - 完整的 AXFR 路径。只能在 IXFR 路径中使用; - **[:FTimestamp:]** - 源上次更新的时间戳(例如 1507946281) - **[:ToTimestamp:]** - 当前时间戳; - 用于提取指标及其过期时间的正则表达式。第一个匹配项是指标,第二个匹配项是过期时间。过期时间是可选参数。正则表达式必须包含在双引号中。如果指定空的正则表达式(`""`),将使用默认正则表达式(`"^([A-Za-z0-9][A-Za-z0-9\-\._]+)[^A-Za-z0-9\-\._]*.*$"`)。如果不需要正则表达式(源已经以所需格式提供数据),则使用 `none`。 可选参数(必须全部使用或全部不使用): - UserID(内部使用)。 - IOC 的最大数量。 - 完整源更新,热缓存时间(以秒为单位)。 - 增量源更新,热缓存时间(以秒为单位)。 HTTPS 源下载会验证远程服务器的 TLS 证书。具有无效或自签名证书的源将下载失败。对于自签名证书,请结合 `curl --insecure` 使用 `shell:` 源。 如果某个源返回的指标数量少于之前的 50%,则该更新将被拒绝,并保留先前的数据。这可以防止质量下降的数据源缩小 RPZ 覆盖范围。可通过 `?SOURCE_MIN_IOC_RATIO` 宏进行配置。 **source** 记录示例: ``` %% Local file source — indicators without expiration {source,{"sample_fqdn","file:cfg/sample_ioc_fqdn.txt","[:AXFR:]",none}}. %% Local file source — indicators with expiration timestamps (tab-separated) {source,{"sample_expire","file:cfg/sample_ioc_expire.txt","[:AXFR:]","^([A-Za-z0-9][A-Za-z0-9\-\._]+)\t([0-9TZ:\-]+)$"}}. %% Shell source — fetch RPZ via AXFR and extract CNAMEs {source,{"base.rpz1","shell:/usr/bin/dig -y KEYNAME:TSIGKEY @127.0.0.1 base.rpz.ioc2rpz.local axfr | /bin/grep -e CNAME | /bin/grep -v '*.' | /usr/bin/awk -F '.base.rpz' '{print $1}'","",none}}. ``` 源 **shell:** 用于扩展 ioc2rpz™ 原生略受限的连接选项。ioc2rpz™ 容器包含 dig、grep、awk 和 python。例如,您可以混合不同的 RPZ 数据源或从数据库获取数据。 **Shell 命令限制:** 所有可执行文件必须使用绝对路径(例如 `/usr/bin/curl` 而非 `curl`)。破坏性命令(`rm`、`bash`、`sh` 等)会被阻止。命令替换(`$(...)`、反引号)和输出重定向(`>`、`>>`)将被拒绝。详情请参见 [docs/configuration.md](docs/configuration.md)。 **本地文件安全:** 出于安全考虑,包含 `..`(父目录遍历)的文件路径将被拒绝。 ### **rpz** 记录 RPZ 项定义了一个响应策略区域。 **rpz** 记录包括: - rpz 名称; - SOA 刷新时间(以秒为单位); - SOA 更新重试时间(以秒为单位); - SOA 过期时间(以秒为单位); - SOA NXDomain TTL(以秒为单位); - 缓存。可能的值:``true`` 或 ``false``。``true`` 表示应对 RPZ 进行缓存,``false`` 表示非缓存的实时区域,源将在 AXFR 请求时被下载并生成 RPZ。“实时”区域不支持增量区域传送。如果 RPZ 数据源没有被缓存,它会被临时存储在热缓存中。如果客户端请求超时,下次我们将能够做出响应。AXFR 时间将用于确定缓存生命周期; - 通配符。可能的值:``true`` 或 ``false``。定义是否应生成通配符规则; - 操作。请参阅下方的 RPZ 操作表; - TSIG 密钥和密钥组列表; - RPZ 中使用的 IOC 类型:``mixed``、``fqdn``、``ip``。用于优化。 - 完整区域更新时间(以秒为单位)(AXFR 时间)。如果 IOC 的 MD5 不同,则进行完整区域更新和重建; - 增量区域更新时间(IXFR 时间)。源应支持增量更新。“0”表示不进行增量区域更新; - 源列表; - 应在 RPZ 更新时收到通知的 DNS 服务器(IP 地址)列表(请参阅 [DNS NOTIFY](#dns-notify)); - 白名单列表。 #### RPZ 操作 | 操作 | 配置值 | 描述 | |--------|-------------|-------------| | NXDOMAIN | `"nxdomain"` | 返回 NXDOMAIN(域名不存在) | | NODATA | `"nodata"` | 返回空应答(域存在,无记录) | | Passthru | `"passthru"` | 允许查询(豁免规则) | | Drop | `"drop"` | 静默丢弃查询 | | TCP-Only | `"tcp-only"` | 强制客户端通过 TCP 重试 | | Block NS | `"blockns"` | 阻止权威名称服务器 | | 重定向 (域名) | `{"redirect_domain","example.com"}` | 重定向到指定域名(`local_cname` 的别名) | | 重定向 (IP) | `{"redirect_ip","127.0.0.1"}` | 重定向到指定 IP(`local_a`/`local_aaaa` 的别名) | | Local A | `{"local_a","127.0.0.1"}` | 返回自定义 IPv4 地址 | | Local AAAA | `{"local_aaaa","fe80::1"}` | 返回自定义 IPv6 地址 | | Local CNAME | `{"local_cname","www.example.com"}` | 返回 CNAME 重定向 | | Local TXT | `{"local_txt","Text Record"}` | 返回 TXT 记录 | 多个本地操作可以在列表中组合:`[{"local_a","127.0.0.1"},{"local_aaaa","fe80::1"},{"local_txt","Blocked"}]` **rpz** 记录示例: ``` {rpz,{"zone_name",soa_refresh, soa_update_retry,soa_expire,soa_nxdomain_ttl,"cache","wildcards","action",["key1","key2"],"Zone_type",AXFT_Time, IXFR_Time,["source1","source2"],["notify_ip1","notify_ip2"],["whitelist_1","whitelist_2"]}}. {rpz,{"zone_name",soa_refresh, soa_update_retry,soa_expire,soa_nxdomain_ttl,"cache","wildcards","action",["key1","key2",{groups,["group1","group2"]}],"Zone_type",AXFT_Time, IXFR_Time,["source1","source2"],["notify_ip1","notify_ip2"],["whitelist_1","whitelist_2"]}}. {rpz,{"mixed.ioc2rpz",7202,3600,2592000,7200,"true","true","passthru",["dnsproxykey_1","dnsproxykey_2"],"mixed",86400,3600,["sample_fqdn","sample_expire","sample_ip"],[],["whitelist_1","whitelist_2"]}}. {rpz,{"mixed.ioc2rpz",7202,3600,2592000,7200,"true","true","passthru",["dnsproxykey_1","dnsproxykey_2",{groups,["public","ip2"]}],"mixed",86400,3600,["sample_fqdn","sample_expire","sample_ip"],[],["whitelist_1","whitelist_2"]}}. ```
示例配置文件(点击展开) ``` {srv,{"ns1.rpz-proxy.com","support.rpz-proxy.com",["dnsmkey_3"],["127.0.0.1","10.42.0.10"]}}. {cert,{"cfg/ioc2rpz_dot.crt", "cfg/ioc2rpz_dot.key", ""}}. {key,{"dnsproxykey_1","md5","apXqLsDs90H213eV6LS9ryYp5tY8YTpkttOkRCve7dp1Zeob3SGAbaVU9BShpsW25MmR8mTiX5OY0Qetv977Yw=="}}. {key,{"dnsproxykey_2","sha512","03uuaGl9kqfenjRgIeCv6e29lVvMwviB1+cDX1I0jcVOcTU4jWFwRkfo3ULRMD+NGDfwzYvXkJ94FNEaAW4vzw=="}}. {key,{"dnsmkey_3","sha512","03uuaGl9kqfenjRgIeCv6e29lVvMwviB1+cDX1I0jcVOcTU4jWFwRkfo3ULRMD+NGDfwzYvXkJ94FNEaAW4vzw=="}}. {whitelist,{"whitelist_1","file:cfg/sample_whitelist.txt",none}}. {whitelist,{"whitelist_2","file:cfg/whitelist2.txt",""}}. {source,{"sample_fqdn","file:cfg/sample_ioc_fqdn.txt","[:AXFR:]",none}}. {source,{"sample_expire","file:cfg/sample_ioc_expire.txt","[:AXFR:]","^([A-Za-z0-9][A-Za-z0-9\\-\\._]+)\\t([0-9TZ:\\-]+)$"}}. {source,{"sample_ip","file:cfg/sample_ioc_ip.txt","[:AXFR:]",none}}. {rpz,{"localdata.ioc2rpz",7202,3600,2592000,7200,"false","true",[{"local_aaaa","fe80::1"},{"local_a","127.0.0.1"},{"local_a","127.0.0.2"},{"local_a","127.0.0.3"},{"local_a","127.0.0.4"},{"local_cname","www.example.com"},{"local_txt","Text Record www.example.com"},{"local_txt","Text Record 2"}],["dnsproxykey_1", "dnsproxykey_2"],"mixed",30,30,["sample_fqdn"],[],["whitelist_1","whitelist_2"]}}. {rpz,{"dga.ioc2rpz",7202,3600,2592000,7200,"true","true","nodata",["dnsproxykey_1","dnsproxykey_2"],"fqdn",172800,3600,["sample_expire"],[],[]}}. {rpz,{"mixed.ioc2rpz",7202,3600,2592000,7200,"true","true","passthru",["dnsproxykey_1", "dnsproxykey_2"],"mixed",86400,3600,["sample_fqdn","sample_expire"],[],["whitelist_1","whitelist_2"]}}. {rpz,{"ip-block.ioc2rpz",7202,3600,2592000,7200,"false","true","nxdomain",["dnsproxykey_1","dnsproxykey_2"],"ip",172800,0,["sample_ip"],[],[]}}. ```
## 预定义配置值 - include/ioc2rpz.hrl include/ioc2rpz.hrl 包含预编译的参数。 标准参数: - ``MGMToDNS`` (true/false) - 启用通过 DNS/TCP 进行管理; - ``DBStorage`` (ets) - 定义 AXFR 和 IXFR 缓存的数据库存储。当前版本仅支持 ETS; - ``SaveETS`` (true/false) - 定义是否应将 ETS AXFR/IXFR 表保存在磁盘上; - ``Port``(数值,1 - 65535)- 定义服务运行的 DNS 端口; - ``PortTLS``(数值,1 - 65535)- 定义服务运行的 DoT 端口; - ``PortREST``(数值,1 - 65535)- 定义服务运行的 HTTPs 端口; - ``TTL``(数值,以秒为单位)- DNS 记录/RPZ 规则的默认 TTL。 - ``DefConf``(字符串)- 默认配置文件; - ``DefDB``(字符串)- 默认数据库路径; - ``logTS`` - 如果已定义,则在日志消息中添加时间戳; - ``debug`` - 如果已定义,则打印调试日志消息; - ``TLSVersion`` ('tlsv1.2-1.3') - DoT 和 REST API 支持的 TLS 版本; 优化参数: - ``DNSPktMax``(数值,100 - 65535)- 最大数据包大小。推荐值: - 16384 - 最小区域传送大小; - 65535 - 最小 DNS 数据包数量; - ``Compression``(数值,0 - 9)- 压缩级别(0 - 无压缩,9 - 最高压缩)。AXFR 缓存和磁盘上的表存储压缩数据; - ``ZoneRefTime``(数值,以毫秒为单位)- 定义区域刷新检查间隔; - ``TCPTimeout``(数值,以毫秒为单位)- 定义 TCP 会话超时时间; - ``HotCacheTime``(数值,以秒为单位)- IOC、规则、数据包的热缓存时间。实时区域存储在热缓存中; - ``HotCacheTimeIXFR``(数值,以秒为单位)- 热缓存中 IXFR IOC 的热缓存时间。默认情况下,IXFR 指标会被缓存一分钟(即使设置为 0),因为当前序列号总是向下取整到前一分钟; - ``RATE_LIMIT_WINDOW``(数值,以毫秒为单位,默认 10000)- 每个 IP 的速率限制窗口持续时间; - ``MAX_REQUESTS_PER_WINDOW``(数值,默认 1)- 每个 IP 在每个速率限制窗口内的最大 DNS 请求数; -ShellMaxRespSize``(数值,默认 2 GiB)- shell 命令源的最大响应大小; - ``SourcePullTimeout``(数值,以毫秒为单位,默认 300000)- 源下载超时(5 分钟); ## AXFR(完整)和 IXFR(增量)缓存如何更新 - AXFR 缓存始终包含没有 SOA/NS/TSIG 记录的预建区域。预建意味着所有记录都已按数据包拆分,且标签已被缩短/压缩。 - 如果服务器收到 AXFR 请求,它将从 AXFR 缓存中检索数据包,并根据需要添加 SOA/NS 记录和 TSIG。 - AXFR 区域更新应被视为一种清理过程,应定期进行。只是为了确保源和缓存之间没有失去同步。 - 对于大型区域,应不频繁地安排 AXFR 更新,以尽量减少对服务器性能和所有客户端数据传输量的影响。 - 如果可能,所有更改都应通过增量区域更新完成。在这种情况下,只有在区域被更新时才会重建 AXFR 缓存。 - [TODO] 由于优化,对于新的 IOC 只会重建最后一个数据包,而对于过期的 IOC 则重建相关和对应的数据包。 - IXFR 缓存仅包含 IOC 和过期日期。[TODO] 以及数据包 ID(以使其可以快速重建区域)。 - RPZ 记录包含当前区域的 Serial 和 Serial_IXFR。Serial_IXFR 作为可用于增量区域传送的最小增量区域序列号。 - 在完整区域更新 (AXFR) 后,IXFR 缓存会被清空。Serial_IXFR = Serial。在任何情况下客户端都将收到完整的区域更新,这就是为什么不频繁地进行 AXFR 区域传送很重要的原因。 - 当 IXFR 缓存被更新时,必须重建 AXFR 缓存。 - 如果某个区域不支持 IXFR 更新 -> 它不会保存在 IXFR 表中。 - 实时区域不会缓存在 AXFR、IXFR 缓存中,但其源 (IOC) 可以缓存在热缓存中。 ## 热缓存 所有 IOC、规则、数据包(包括实时 RPZ)都存储在热缓存中。预编译参数 ``HotCacheTime``、``HotCacheTimeIXFR`` 定义了存储时间。 ## 如何试用 ioc2rpz™(或由 ioc2rpz™ 托管的示例和免费 RPZ 数据源) ### 免责声明 作者对这些 RPZ 数据源中的任何错误或遗漏不承担任何责任或义务。这些数据源按“原样”提供,不保证完整性、准确性、实用性或时效性,仅用于演示 ioc2rpz™ 技术。RPZ 数据源的分发服务可能会在不提前通知的情况下中断或停止。作者对因使用本服务而造成的任何直接或间接损害概不负责。 ### RPZ 数据源 如果您在 [ioc2rpz™ 社区](https://ioc2rpz.net)注册,您可以使用以下数据源测试 ioc2rpz™ 技术: - [notracking](https://github.com/notracking/hosts-blocklists); - [Phishtank](https://www.phishtank.com/)。 ### BIND 示例配置 ``` options { #This is just options for RPZs. Add other options as required recursion yes; response-policy { ####FQDN only zones ####Mixed zones zone "phishtank.ioc2rpz" policy nxdomain; ####IP only zones } qname-wait-recurse no break-dnssec yes; }; key "ioc2rpz-YOUR-UNIQUE-KEY-NAME"{ algorithm hmac-sha256; secret "ioc2rpz-YOUR-UNIQUE-KEY"; }; zone "phishtank.ioc2rpz" { type slave; file "/var/cache/bind/phishtank.ioc2rpz"; masters {94.130.30.123 key "ioc2rpz-YOUR-UNIQUE-KEY-NAME";}; }; ``` ### PowerDNS 示例配置 ``` rpzMaster("94.130.30.123", "phishtank.ioc2rpz", {defpol=Policy.NXDOMAIN, tsigname="ioc2rpz-YOUR-UNIQUE-KEY-NAME", tsigalgo="hmac-sha256", tsigsecret="ioc2rpz-YOUR-UNIQUE-KEY"}) ``` ### Infoblox 示例配置(导入文件) ``` header-responsepolicyzone,fqdn*,zone_format*,rpz_policy,substitute_name,view,zone_type,external_primaries,grid_secondaries,priority responsepolicyzone,phishtank.ioc2rpz,FORWARD,Nxdomain,,default,responsepolicy,srv_1/94.130.30.123/FALSE/FALSE/TRUE/ioc2rpz-YOUR-UNIQUE-KEY-NAME/ioc2rpz-YOUR-UNIQUE-KEY/HMAC-SHA256,infoblox.localdomain/False/False/False,0 ``` ### DIG 示例(获取 SOA) ``` dig @94.130.30.123 -y hmac-sha256:ioc2rpz-YOUR-UNIQUE-KEY-NAME:ioc2rpz-YOUR-UNIQUE-KEY phishtank.ioc2rpz SOA kdig @94.130.30.123 -y hmac-sha256:ioc2rpz-YOUR-UNIQUE-KEY-NAME:ioc2rpz-YOUR-UNIQUE-KEY phishtank.ioc2rpz SOA +tls ``` ## 一些免费的威胁情报源 - [Netlab](http://data.netlab.360.com) - [GitHub 上的 awesome-threat-intelligence 列表](https://github.com/hslatman/awesome-threat-intelligence) 您可以在 Wiki 页面上找到其他 IOC 数据源:https://github.com/Homas/ioc2rpz/wiki/IOC-Sources。 ## 更多文档 有关详细的文档,请参见 `docs/` 目录: - [docs/architecture.md](docs/architecture.md) — OTP 监督树、模块职责、ETS 表、数据流 - [docs/configuration.md](docs/configuration.md) — 包含所有元组类型和选项的完整配置参考 - [docs/deployment.md](docs/deployment.md) — 构建说明、Docker 部署、证书、监控、故障排除 - [docs/protocols.md](docs/protocols.md) — 协议支持 (UDP/TCP/DoT/DoH)、REST API、TSIG、速率限制、DNS NOTIFY ## 参考文献 - [RFC-6895 Domain Name System (DNS) IANA Considerations](https://tools.ietf.org/html/rfc6895) - [RFC-1035 Domain Names - Implementation and Specification](https://tools.ietf.org/html/rfc1035) - [RFC-1995 Incremental Zone Transfer in DNS](https://tools.ietf.org/html/rfc1995) - [DNS Response Policy Zones (RPZ)](https://tools.ietf.org/html/draft-ietf-dnsop-dns-rpz-00) + [vixie](https://tools.ietf.org/html/draft-vixie-dns-rpz-02) - [RFC-2845 Secret Key Transaction Authentication for DNS (TSIG)](https://tools.ietf.org/html/rfc2845) - [RFC-2104 HMAC: Keyed-Hashing for Message Authentication](https://tools.ietf.org/html/rfc2104) - [RFC-4635 HMAC SHA TSIG Algorithm Identifiers](https://tools.ietf.org/html/rfc4635) - [RFC-5966 DNS Transport over TCP - Implementation Requirements](https://tools.ietf.org/html/rfc5966) - [RFC-1996 A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)](https://tools.ietf.org/html/rfc1996) - [Extension Mechanisms for DNS (EDNS(0))](https://tools.ietf.org/html/rfc6891) + [EDNS Option Codes](https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11) - [RFC-7873 Domain Name System (DNS) Cookies](https://tools.ietf.org/html/rfc7873) - [RFC-7858 Specification for DNS over Transport Layer Security (TLS)](https://tools.ietf.org/html/rfc7858) - [Cowboy Web Server](https://ninenines.eu) - [Rebar3](https://www.rebar3.org)
CEF 事件代码参考(点击展开) | 代码 | 严重性 | 事件 | 描述 | |------|----------|-------|-------------| | 101 | 低 | 错误的 DNS 数据包 | 收到格式错误的 DNS 数据包 | | 102 | 低 | 错误的 DNS 请求 | 无法解析的 DNS 请求 | | 103 | 中 | 已拒绝 | DNS 请求被拒绝 | | 104 | 中 | 找不到 TSIG 密钥 | 请求使用了未知的 TSIG 密钥 | | 105 | 中 | TSIG 错误的 MAC | TSIG 签名验证失败 | | 106 | 中 | TSIG 错误的时间 | TSIG 时间戳超出范围 | | 107 | 中 | 其他 TSIG 错误 | 未分类的 TSIG 错误 | | 108 | 中 | 错误的 TSIG 位置 | TSIG 记录出现在意外位置 | | 109 | 低 | 收到 DNS 响应 | 收到意外的 DNS 响应 | | 120 | 中 | 找不到 RPZ | 请求的 RPZ 区域不存在 | | 121 | 低 | RPZ 未就绪 | RPZ 区域仍在加载/更新中 | | 130 | 低 | RPZ 传送错误 | 区域传送期间发生错误 | | 131 | 低 | RPZ 传送关闭 | 远程端在传送期间关闭了连接 | | 135 | 高 | REST 管理被拒绝 | REST 管理请求被 ACL 拒绝 | | 136 | 高 | 管理请求失败 | 管理请求处理失败 | | 137 | 高 | 不支持的请求 | 未知的 REST API 端点 | | 138 | 高 | 找不到区域 | REST API 引用了不存在的区域 | | 140 | 高 | REST 基础认证失败 | REST API 基础认证失败 | | 141 | 高 | REST 授权失败 | REST API 授权失败 | | 150 | 低 | Shell 命令已执行 | Shell 源命令已执行(信息) | | 151 | 高 | Shell 命令被拒绝 | Shell 源命令被拒绝(安全原因) | | 201 | 低 | RPZ 传送成功 | 区域传送完成 | | 202 | 低 | DNS 查询 | 已处理标准 DNS 查询 | | 221 | 低 | DNS 通知 | 已向辅助服务器发送通知 | | 222 | 中 | DNS 通知错误 | 发送通知失败 | | 230 | 高 | 管理请求 | 已执行管理操作 | | 301 | 高 | 管理请求被拒绝 | DNS 管理命令被拒绝 | | 429 | 高 | 请求过多 | 超出速率限制 | | 501 | 高 | 疑似 DDoS | 检测到 CVE-2004-0789 攻击模式 |
# 您想支持这个项目吗? 您可以通过 [GitHub Sponsor](https://github.com/sponsors/Homas)(定期付款)支持 ioc2rpz™ 项目和 ioc2rpz™ 社区。要进行一次性捐款,您可以使用 [PayPal](https://paypal.me/ioc2rpz) 或 Zelle(我们的邮箱:zelle [at] ioc2rpz [.] net)。 # 支持者 感谢 **craSH** 和 **rrbone** 在 [GitHub Sponsor](https://github.com/sponsors/Homas) 上对我的项目的支持。 # 联系我们 您可以通过电子邮件联系我们:feedback(at)ioc2rpz[.]net,或者在 [Telegram](https://t.me/ioc2rpz) 上联系。 # 许可证 版权所有 2017 - 2025 Vadim Pavlov ioc2rpz[at]gmail[.]com 根据 Apache 许可证 2.0 版("许可证")获得许可;除非遵守许可证,否则您不得使用此文件。 您可以在以下位置获取许可证副本: ``` http://www.apache.org/licenses/LICENSE-2.0 ``` 除非适用法律要求或书面同意,否则根据许可证分发的软件是按“原样” basis 分发的,不附带任何明示或暗示的担保或条件。请参阅许可证以了解管辖权限和限制的具体语言。
标签:AWS, AXFR, DNS over HTTPS, DNS over TLS, DNS服务器, DNS防火墙, Docker, Docker Compose, DoH, DoT, DPI, Erlang, Erlang/OTP, IoC, IXFR, NIDS, REST API, RPZ, 云部署, 响应策略区, 域名安全, 威胁情报, 威胁阻断, 安全监控, 安全防御评估, 容器化, 开发者工具, 开源, 情报转换, 网络安全, 网络过滤, 请求拦截, 隐私保护, 黑名单