跳到主要内容

执行器插件

执行器是 ForgeDNS 的核心动作层。它们可以读写请求、设置响应、调用上游、缓存结果、做回退、记录日志,或触发系统联动。

阅读本章时,应重点关注以下两个问题:

  1. 这个插件是在“正向阶段”生效,还是在“回程阶段”也会改写结果?
  2. 它是主路径动作,还是观测/副作用动作?

sequence

作用

把多个 matcher 和 executor 编排成一条流水线,是最常用的入口执行器。

参数

- tag: seq_main
type: sequence
args:
- matches: "$cache_hit"
exec: "accept"
- matches: "qname $local_domains"
exec: "$hosts_main"
- matches: "!$has_resp"
exec: "$forward_main"

每条规则字段:

  • matches
    • 可选。
    • 单个 matcher 字符串或 matcher 字符串数组。
  • exec
    • 可选。
    • 可以是:
      • $tag
      • quick setup 语法
      • 内建控制流

配置项详解

sequenceargs 为规则数组,数组中的每个元素代表一条顺序执行规则。

args

  • 类型:array;必填:是;默认值:无
  • 作用:定义 sequence 的规则链。
  • 运行影响:
    • 规则按书写顺序依次执行。
    • args 为空时插件初始化失败。

args[].matches

  • 类型:stringarray
  • 必填:否
  • 默认值:无
  • 作用:定义当前规则的匹配条件。
  • 支持形式:
    • 单个 matcher 字符串
    • 多个 matcher 组成的列表
  • 运行影响:
    • 多个条件之间为逻辑与关系。
    • 未配置时表示无前置匹配条件。

args[].exec

  • 类型:string;必填:否;默认值:无
  • 作用:定义规则命中后要执行的动作。
  • 支持内容:
    • 插件引用
    • quick setup 表达式
    • 内建控制流
  • 运行影响:
    • 直接决定当前规则的执行行为。

行为说明

  • 按顺序执行规则。
  • 一条规则里多个 matches 需要同时为真。
  • 可以通过 jump / goto 调用其它 sequence

典型用途

  • 统一总入口。
  • 把缓存、本地应答、转发、联动拆分成可读的策略层。
  • 通过 marks、matchers 做复杂分支。

注意事项

  • 被引用的插件必须已经定义。
  • sequence 至少需要一条规则。

forward

作用

向上游发起 DNS 查询。

参数

- tag: forward_main
type: forward
args:
concurrent: 2
upstreams:
- addr: "udp://1.1.1.1:53"
- addr: "https://resolver.example/dns-query"
bootstrap: "8.8.8.8:53"
timeout: 5s
enable_http3: true
  • concurrent
    • 多上游并发扇出数量。
    • 默认 1
    • 实际会被限制在 1..=3
  • upstreams
    • 必填,上游列表。
    • 单上游时是单路转发,多上游时是竞争式转发。

配置项详解

concurrent

  • 类型:integer;必填:否;默认值:1
  • 取值范围:实际运行时会限制在 1..=3
  • 作用:定义多上游模式下的并发查询扇出数。
  • 运行影响:
    • 值越大,多上游竞争越积极,但同时会增加上游请求量。

upstreams

  • 类型:array;必填:是;默认值:无
  • 作用:定义一个或多个上游目标。
  • 运行影响:
    • 数组长度为 1 时使用单上游模式。
    • 数组长度大于 1 时使用竞争式查询模式。

upstreams[].addr

  • 类型:string;必填:是;默认值:无
  • 作用:定义上游地址、协议类型以及目标主机。
  • 示例:
    • addr: "8.8.8.8:53"
    • addr: "tls://dns.example:853"
    • addr: "https://resolver.example/dns-query"
  • 支持格式:
    • udp://8.8.8.8:538.8.8.8:53
    • tcp://8.8.8.8:53
    • tcp+pipeline://8.8.8.8:53
    • tls://dns.example:853
    • tls+pipeline://dns.example:853
    • quic://dns.example:853doq://dns.example:853
    • https://resolver.example/dns-querydoh://resolver.example/dns-query
    • h3://resolver.example/dns-query
  • 规则说明:
    • 未写协议时,按 udp:// 处理。
    • https:// / doh:// 表示 DoH,h3:// 表示强制 DoH over HTTP/3。
    • tcp+pipeline://tls+pipeline:// 会直接启用流水线模式。
    • DoH 地址应包含实际请求路径,例如 /dns-query
  • 配置建议:域名型上游建议同时配置 bootstrap,避免形成引导解析依赖。

upstreams[].tag

  • 类型:string;必填:否;默认值:无
  • 作用:为单个上游提供日志标识,便于排查多上游竞争结果。
  • 示例:tag: "upstream_google"

upstreams[].dial_addr

  • 类型:ip;必填:否;默认值:无
  • 作用:指定实际连接 IP,同时保留 addr 中的主机名用于 SNI、Host 和证书校验。
  • 示例:dial_addr: "1.1.1.1"
  • 适用场景:固定拨号地址、绕过本机解析或配合自定义路由出口。

upstreams[].port

  • 类型:integer;必填:否;默认值:协议默认端口
  • 作用:覆盖协议默认端口。
  • 示例:port: 5353

upstreams[].bootstrap

  • 类型:string;必填:否;默认值:无
  • 作用:为域名型上游提供引导解析服务器。
  • 示例:
    • bootstrap: "8.8.8.8:53"
    • bootstrap: "[2606:4700:4700::1111]:53"
  • 规则说明:
    • 仅在 addr 使用域名时有意义。
    • 应写为 IP:port,不能再写域名。
    • 典型用于 DoT、DoQ、DoH 域名上游的首次解析。

upstreams[].bootstrap_version

  • 类型:integer;必填:否;默认值:无
  • 作用:指定 bootstrap 优先使用 IPv4 或 IPv6。
  • 示例:
    • bootstrap_version: 4
    • bootstrap_version: 6
  • 取值:46

upstreams[].socks5

  • 类型:string;必填:否;默认值:无
  • 作用:为上游连接指定 SOCKS5 代理。
  • 示例:
    • socks5: "127.0.0.1:1080"
    • socks5: "user:pass@127.0.0.1:1080"
    • socks5: "user:pass@[2001:db8::1]:1080"
  • 支持格式:
    • host:port
    • username:password@host:port
    • IPv6 需写成 [addr]:port
    • 带认证的 IPv6 需写成 username:password@[addr]:port
  • 规则说明:
    • 代理主机可以是 IP,也可以是主机名;主机名会使用系统解析。
    • 认证部分只按第一个 : 分割用户名和密码,因此格式必须是 username:password@...
    • 上游启用 enable_http3 时不应再配置 socks5,两者不属于同一连接模型。
  • 注意事项:格式错误、端口非法或代理主机解析失败时,该上游不会被正常创建。

upstreams[].idle_timeout

  • 类型:integer;必填:否;默认值:无
  • 单位:秒
  • 作用:定义连接池空闲连接保留时间。
  • 示例:idle_timeout: 30

upstreams[].max_conns

  • 类型:integer;必填:否;默认值:实现默认值
  • 作用:定义连接池连接上限。
  • 示例:max_conns: 256

upstreams[].insecure_skip_verify

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制是否跳过 TLS 证书校验。
  • 示例:insecure_skip_verify: true
  • 注意事项:仅适用于测试、自签证书或受控环境。

upstreams[].timeout

  • 类型:duration;必填:否;默认值:5s
  • 作用:定义单次上游查询超时。
  • 示例:timeout: 3s

upstreams[].enable_pipeline

  • 类型:boolean;必填:否;默认值:协议默认行为
  • 作用:控制 TCP 或 DoT 流水线。
  • 示例:enable_pipeline: true
  • 说明:也可直接通过 tcp+pipeline://tls+pipeline://addr 中启用。

upstreams[].enable_http3

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制 DoH 是否使用 HTTP/3。
  • 示例:enable_http3: true
  • 说明:也可直接通过 h3://addr 中启用。

upstreams[].so_mark

  • 类型:integer;必填:否;默认值:无
  • 作用:设置 Linux SO_MARK
  • 示例:so_mark: 100

upstreams[].bind_to_device

  • 类型:string;必填:否;默认值:无
  • 作用:设置 Linux SO_BINDTODEVICE
  • 示例:bind_to_device: "eth1"

quick setup

- exec: "forward 1.1.1.1"
- exec: "forward 1.1.1.1 8.8.8.8"

说明:

  • 单个地址创建单上游转发。
  • 多个地址创建并发竞争转发。
  • quick setup 只接受地址列表,进阶参数需要完整插件形式。

行为说明

  • 单上游模式:直接查询该上游。
  • 多上游模式:从随机起点选择上游并发查询,先返回成功结果者胜出。
  • 当与 prefer_ipv4 / prefer_ipv6 联动时,支持额外 preferred qtype probe。

常见用途

  • 标准转发。
  • 多上游容错。
  • 多协议混合上游。

注意事项

  • 需要更细的并发、代理、引导解析、HTTP/3 参数时,使用完整 upstreams 配置。
  • 多上游越多并不一定越好,先保证上游分组语义清晰。

cache

作用

对响应做 TTL 感知缓存,支持负缓存与持久化。

参数

- tag: cache_main
type: cache
args:
size: 8192
short_circuit: true
cache_negative: true
max_negative_ttl: 300
negative_ttl_without_soa: 60
max_positive_ttl: 600
ecs_in_key: false
dump_file: "./dns_cache.dump"
dump_interval: 600
  • size
    • 最大缓存条目数。
    • 默认 1024
  • lazy_cache_ttl
    • 可选,强制覆盖缓存写入 TTL。
  • dump_file
    • 可选,缓存持久化文件路径。
  • dump_interval
    • 可选,持久化周期,秒。
    • 默认 600
  • short_circuit
    • 命中缓存后是否短路后续执行。
  • cache_negative
    • 是否缓存 NXDOMAIN/NODATA。
  • max_negative_ttl
    • 负缓存最大 TTL。
    • 默认 300
  • negative_ttl_without_soa
    • 无 SOA 的负响应回退 TTL。
    • 默认 60
    • 若设为 0,无 SOA 负响应不会缓存。
  • max_positive_ttl
    • 正常响应 TTL 上限。
  • ecs_in_key
    • 是否把 ECS scope 纳入缓存 key。
    • 默认 false

配置项详解

size

  • 类型:integer;必填:否;默认值:1024
  • 作用:定义缓存最大条目数。

lazy_cache_ttl

  • 类型:integer;必填:否;默认值:无
  • 单位:秒
  • 作用:覆盖写入缓存时使用的 TTL。

dump_file

  • 类型:string;必填:否;默认值:无
  • 作用:指定缓存持久化文件路径。

dump_interval

  • 类型:integer;必填:否;默认值:600
  • 单位:秒
  • 作用:定义缓存定期落盘周期。

short_circuit

  • 类型:boolean;必填:否;默认值:实现默认行为
  • 作用:控制缓存命中后是否立即结束后续执行。

cache_negative

  • 类型:boolean;必填:否;默认值:实现默认行为
  • 作用:控制是否缓存 NXDOMAIN 与 NODATA。

max_negative_ttl

  • 类型:integer;必填:否;默认值:300
  • 单位:秒
  • 作用:定义负缓存 TTL 上限。

negative_ttl_without_soa

  • 类型:integer;必填:否;默认值:60
  • 单位:秒
  • 作用:定义无 SOA 负响应的回退 TTL。

max_positive_ttl

  • 类型:integer;必填:否;默认值:无
  • 单位:秒
  • 作用:定义正响应 TTL 上限。

ecs_in_key

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制 ECS scope 是否参与缓存键计算。

行为说明

  • 既会读缓存,也会在后续拿到响应后写缓存。
  • 命中缓存时,返回缓存副本并按剩余 TTL 输出。
  • 内置过期清理和近似 LRU 回收。

插件 API

  • GET /plugins/<tag>/flush
    • 清空缓存。
  • GET /plugins/<tag>/dump
    • 导出缓存内容。
  • POST /plugins/<tag>/load_dump
    • 导入缓存 dump。

典型用途

  • 所有转发入口前置缓存。
  • 构建高命中率低时延策略。
  • 在可控场景中持久化缓存,加快重启后恢复。

注意事项

  • 如果前面有会直接生成本地应答的插件,放置位置会决定这些结果是否进入缓存。
  • ecs_in_key 开启后,缓存碎片会明显增加。

fallback

作用

在主路径失败或过慢时,切换到备用路径。

参数

- tag: fallback_main
type: fallback
args:
primary: "forward_fast"
secondary: "forward_stable"
threshold: 200
always_standby: true
  • primary
    • 必填,主执行器。
  • secondary
    • 必填,备用执行器。
  • threshold
    • 触发备用路径的阈值,毫秒。
    • 默认 0
  • always_standby
    • 是否从一开始并发待命备用路径。
    • 默认 false

配置项详解

primary

  • 类型:string;必填:是;默认值:无
  • 作用:指定主执行器。

secondary

  • 类型:string;必填:是;默认值:无
  • 作用:指定备用执行器。

threshold

  • 类型:integer;必填:否;默认值:0
  • 单位:毫秒
  • 作用:定义主路径超时或延迟判定阈值。

always_standby

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制备用路径是否与主路径同时待命。

行为说明

  • 正向启动主路径。
  • 到达阈值或主路径失败后启动/释放备用路径。
  • 谁先拿到有效响应,谁赢。
  • 另一分支会被取消。

典型用途

  • 快速上游 + 稳定上游的双层回退。
  • 不同协议上游之间的故障兜底。

注意事项

  • 这是“路径级”回退,不是“记录级”合并。
  • always_standby 可以降低尾延迟,但会放大上游开销。

hosts

作用

按域名规则直接返回静态 A / AAAA

参数

- tag: hosts_main
type: hosts
args:
entries:
- "full:router.local 192.168.1.1"
- "domain:svc.local 10.0.0.10 fd00::10"
files:
- "/etc/forgedns/hosts.txt"
  • entries
    • 内联 hosts 规则。
  • files
    • 外部规则文件。

配置项详解

entries

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义内联 hosts 规则。
  • 规则格式:
    • <域名规则> <ip1> <ip2> ...

files

  • 类型:array;必填:否;默认值:空数组
  • 作用:指定外部 hosts 规则文件列表。

规则格式:

<域名规则> <ip1> <ip2> ...

行为说明

  • 仅处理 IN 类的 A / AAAA 请求。
  • 根据查询类型返回同族地址。
  • 未命中时透传后续执行。
  • TTL 固定为 300

典型用途

  • 本地服务名。
  • 固定内部地址映射。
  • 小规模静态域名覆盖。

arbitrary

作用

加载任意静态 DNS 记录并在命中时直接构造应答。

参数

- tag: arbitrary_main
type: arbitrary
args:
rules:
- "example.com. 60 IN TXT \"hello world\""
- "mail.example.com. 300 IN MX 10 mx1.example.com."
files:
- "/etc/forgedns/zone.txt"
  • rules
    • 内联记录文本。
  • files
    • 记录文件。

配置项详解

rules

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义内联静态记录列表。

files

  • 类型:array;必填:否;默认值:空数组
  • 作用:指定静态记录文件列表。

行为说明

  • 查询名与类型匹配时,直接生成本地应答。
  • ANY 查询会返回该名称下全部已加载记录。
  • 常见 A / AAAA 走了快路径优化。

典型用途

  • 少量静态权威式记录。
  • 本地 TXT / MX / PTR / CNAME 数据。
  • 测试或实验环境的本地响应。

注意事项

  • 这是“静态响应生成器”,不负责 zone 传送或权威服务器全语义。

redirect

作用

把请求域名改写为另一个目标域名,并在返回阶段补回客户端可见的 CNAME。

参数

- tag: redirect_main
type: redirect
args:
rules:
- "full:old.example.com new.example.net"
files:
- "/etc/forgedns/redirect.txt"
  • rules
    • 内联重定向规则。
  • files
    • 外部规则文件。

配置项详解

rules

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义内联重定向规则。
  • 规则格式:
    • <域名规则> <目标域名>

files

  • 类型:array;必填:否;默认值:空数组
  • 作用:指定外部重定向规则文件列表。

规则格式:

<域名规则> <目标域名>

行为说明

  • 正向阶段:改写请求的 QUESTION NAME。
  • 回程阶段:
    • 把 response question 中的目标名还原为原始名。
    • 在 answers 里追加一条 CNAME original -> target

典型用途

  • 统一入口域名指向另一套记录。
  • 对特定域名做别名跳转而不改客户端配置。

注意事项

  • 更适合 A/AAAA/TXT 这类简单请求。
  • 对复杂记录和某些扩展场景不保证完全语义透明。

reverse_lookup

作用

缓存应答中的 IP -> 域名关系,并可选地处理 PTR 查询。

参数

- tag: reverse_lookup_main
type: reverse_lookup
args:
size: 65535
ttl: 7200
handle_ptr: true
  • size
    • 最大缓存项数。
    • 默认 65535
  • handle_ptr
    • 是否直接处理 PTR 请求。
    • 默认 false
  • ttl
    • 反查缓存 TTL,秒。
    • 默认 7200

配置项详解

size

  • 类型:integer;必填:否;默认值:65535
  • 作用:定义反查缓存容量上限。

handle_ptr

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制是否直接用反查缓存响应 PTR 请求。

ttl

  • 类型:integer;必填:否;默认值:7200
  • 单位:秒
  • 作用:定义 IP 到域名映射的缓存 TTL。

行为说明

  • handle_ptr: true 且 PTR 命中缓存,会直接返回 PTR 响应并停止后续链路。
  • 正常回程阶段会扫描 A / AAAA answers,把 IP 与请求域名写入缓存。
  • 会把记录 TTL 限制在插件配置 TTL 上限内。

插件 API

  • GET /plugins/<tag>?ip=<ip>
    • 返回命中的完全限定域名。

典型用途

  • 本地快速 IP 反查。
  • 策略排障、日志联动、资产可视化。

注意事项

  • 推荐放置在 cache 之前,否则缓存命中可能绕过该插件,导致反查表不更新。

ecs_handler

作用

处理 EDNS Client Subnet。

参数

- tag: ecs_main
type: ecs_handler
args:
forward: false
send: true
mask4: 24
mask6: 48

- tag: ecs_preset
type: ecs_handler
args:
preset: "203.0.113.10"
mask4: 24
  • forward
    • 是否保留客户端自带 ECS。
    • 默认 false
  • send
    • 请求里没有 ECS 时,是否根据客户端 IP 自动补 ECS。
    • 默认 false
  • preset
    • 固定 ECS 来源 IP。
  • mask4
    • IPv4 ECS 前缀长度。
    • 默认 24
  • mask6
    • IPv6 ECS 前缀长度。
    • 默认 48

配置项详解

forward

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制是否保留客户端请求中已有的 ECS。

send

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制在请求缺少 ECS 时,是否根据来源地址自动补充 ECS。

preset

  • 类型:string;必填:否;默认值:无
  • 作用:指定固定的 ECS 来源地址。

mask4

  • 类型:integer;必填:否;默认值:24
  • 作用:指定 IPv4 ECS 前缀长度。

mask6

  • 类型:integer;必填:否;默认值:48
  • 作用:指定 IPv6 ECS 前缀长度。

quick setup

- exec: "ecs_handler 203.0.113.10/24"

当前 quick setup 主要用于传入 preset IP。涉及高级开关时,应使用完整配置形式。

行为说明

  • 正向阶段:
    • 可删掉已有 ECS。
    • 可保留已有 ECS。
    • 可根据客户端地址或 preset 注入 ECS。
  • 回程阶段:
    • 如果 ECS 不是从客户端原样转发的,会把响应里的 ECS 去掉,避免泄露内部构造信息。

典型用途

  • 面向策略上游携带客户端网段信息。
  • 在网关场景下根据访问来源做更细粒度结果优化。

注意事项

  • mask4 最大 32mask6 最大 128

forward_edns0opt

作用

把指定 EDNS0 option code 从下游请求转发到最终响应中。

参数

- tag: edns_forward
type: forward_edns0opt
args:
codes: [10, 12]
  • codes
    • 允许转发的 option code 列表。

配置项详解

codes

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义允许从请求复制到响应中的 EDNS0 option code 集合。
  • 运行影响:
    • 未配置时插件基本退化为无操作。

quick setup

- exec: "forward_edns0opt 10,12"

行为说明

  • 正向阶段从请求里收集目标 option。
  • 回程阶段把这些 option 写回响应的 OPT 记录。
  • 会做去重。

典型用途

  • 透传特定 EDNS0 扩展。
  • 在策略链中保留与下游会话有关的附加元数据。

ttl

作用

改写响应 TTL。

参数

对象形式:

- tag: ttl_main
type: ttl
args:
fix: 300

或:

- tag: ttl_clamp
type: ttl
args:
min: 60
max: 600
  • fix
    • 强制所有 TTL 为固定值。
  • min
    • TTL 下限。
  • max
    • TTL 上限。

配置项详解

fix

  • 类型:integer;必填:否;默认值:无
  • 作用:将所有响应 TTL 固定为同一个值。

min

  • 类型:integer;必填:否;默认值:无
  • 作用:定义 TTL 下限。

max

  • 类型:integer;必填:否;默认值:无
  • 作用:定义 TTL 上限。

quick setup

- exec: "ttl 300"
- exec: "ttl 60-600"

行为说明

  • 会改写 answers、authority、additionals 中的 TTL。
  • 适合放在获得响应之后。

典型用途

  • 缩短高波动域名的 TTL。
  • 统一本地策略结果的缓存行为。

prefer_ipv4 / prefer_ipv6

作用

双栈优选器。对偏好类型做学习,对非偏好类型做抑制。

参数

- tag: prefer_v4
type: prefer_ipv4
args:
cache: true
cache_ttl: 3600
  • cache
    • 是否缓存 preferred 结果状态。
    • 默认 true
  • cache_ttl
    • 状态缓存秒数。
    • 默认 3600

配置项详解

cache

  • 类型:boolean;必填:否;默认值:true
  • 作用:控制是否缓存 preferred 类型存在状态。

cache_ttl

  • 类型:integer;必填:否;默认值:3600
  • 单位:秒
  • 作用:定义 preferred 状态缓存时长。

行为说明

  • prefer_ipv4
    • 偏好 A
  • prefer_ipv6
    • 偏好 AAAA
  • 偏好类型请求正常放行,并记录“该域名存在 preferred answer”。
  • 非偏好类型请求:
    • 若缓存已知 preferred answer 存在,则直接返回空成功响应抑制该类型。
    • 否则借助 forward 的 probe 机制进行一次 preferred 类型探测,再决定是否抑制。

典型用途

  • 客户端双栈策略收敛。
  • 某些网络环境下优先收敛到更稳定的一类地址。

注意事项

  • 该插件与 forward 联动最为紧密,通常放置在 forward 之前并通过 continuation 生效。

black_hole

作用

对命中的 A / AAAA 请求直接返回预设地址。

参数

- tag: sinkhole
type: black_hole
args:
ips:
- "0.0.0.0"
- "::"
  • ips
    • 预设返回 IP。
    • IPv4 用于 A,IPv6 用于 AAAA。

配置项详解

ips

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义本地合成返回地址集合。
  • 运行影响:
    • IPv4 地址仅用于 A 应答。
    • IPv6 地址仅用于 AAAA 应答。

quick setup

- exec: "black_hole 0.0.0.0 ::"

行为说明

  • A 查询返回配置中的 IPv4 地址。
  • AAAA 查询返回配置中的 IPv6 地址。
  • 其它类型透传。

典型用途

  • 拦截、黑洞、占位地址返回。

drop_resp

作用

清空当前上下文中的响应。

参数

无参数。

配置项详解

无配置项。

quick setup

- exec: "drop_resp"

行为说明

  • 仅清理 context.response
  • 不会清 marks 或请求元信息。

典型用途

  • 覆盖前面错误或不满意的响应结果。
  • 配合后续重新转发或重建响应。

sleep

作用

异步延迟,用于测试和策略实验。

参数

- tag: sleep_100ms
type: sleep
args:
duration: 100
  • duration
    • 毫秒。
    • 默认 0

配置项详解

duration

  • 类型:integer;必填:否;默认值:0
  • 单位:毫秒
  • 作用:定义当前请求在该执行器上的额外异步等待时间。

quick setup

- exec: "sleep 100"

典型用途

  • 测试 fallback 阈值。
  • 人工制造慢路径验证观测链路。

debug_print

作用

打印请求与响应对象,便于调试。

参数

- tag: debug_main
type: debug_print
args:
msg: "before forward"
  • msg
    • 可选日志标题。
    • 默认 "debug print"

配置项详解

msg

  • 类型:string;必填:否;默认值:"debug print"
  • 作用:定义日志输出标题。

quick setup

- exec: "debug_print cache branch"

典型用途

  • 排查 sequence 分支。
  • 验证请求和响应在插件前后是否被改写。

query_summary

作用

在后续链路执行完后输出紧凑查询摘要。

参数

- tag: summary_main
type: query_summary
args:
msg: "main pipeline"
  • msg
    • 可选标题。
    • 默认 "query summary"

配置项详解

msg

  • 类型:string;必填:否;默认值:"query summary"
  • 作用:定义摘要日志标题。

quick setup

- exec: "query_summary main"

行为说明

  • 正向阶段记录开始时间。
  • 回程阶段输出:
    • 来源地址
    • qname
    • qtype
    • rcode
    • elapsed_ms

典型用途

  • 低成本链路追踪。
  • 分支延时对比。

metrics_collector

作用

收集轻量级请求计数与延时指标,并导出 Prometheus 格式。

参数

- tag: metrics_main
type: metrics_collector
args:
name: "main"
  • name
    • 指标标签名。
    • 默认 "default"

配置项详解

name

  • 类型:string;必填:否;默认值:"default"
  • 作用:定义当前指标收集器的名称标签。

quick setup

- exec: "metrics_collector main"

行为说明

  • 正向阶段:
    • query_total +1
    • inflight +1
    • 记录开始时间
  • 回程阶段:
    • inflight -1
    • 若无响应则 err_total +1
    • 若有响应则累计延时

API

  • GET /metrics
    • Prometheus 文本格式。

典型用途

  • 主链路观测。
  • 多条策略入口延时对比。

ipset

作用

把响应中的 IP 写入 Linux ipset

参数

- tag: ipset_main
type: ipset
args:
set_name4: "forgedns_v4"
set_name6: "forgedns_v6"
mask4: 24
mask6: 64
  • set_name4
    • A 记录写入的 IPv4 set 名。
  • set_name6
    • AAAA 记录写入的 IPv6 set 名。
  • mask4
    • IPv4 前缀长度。
    • 默认 24
  • mask6
    • IPv6 前缀长度。
    • 默认 32

配置项详解

set_name4

  • 类型:string;必填:否;默认值:无
  • 作用:指定写入 IPv4 地址的 ipset 名称。

set_name6

  • 类型:string;必填:否;默认值:无
  • 作用:指定写入 IPv6 地址的 ipset 名称。

mask4

  • 类型:integer;必填:否;默认值:24
  • 作用:指定 IPv4 地址写入 ipset 时使用的前缀长度。

mask6

  • 类型:integer;必填:否;默认值:32
  • 作用:指定 IPv6 地址写入 ipset 时使用的前缀长度。

quick setup

- exec: "ipset forgedns_v4,4,24 forgedns_v6,6,64"

格式:

<set_name>,<family>,<mask>

其中 family46

行为说明

  • 从 answer 中提取唯一 A/AAAA 地址。
  • 根据地址族写入相应 set。
  • 通过非阻塞队列投递到后台 writer。

典型用途

  • 基于 DNS 结果驱动后续流量策略。
  • DNS 到防火墙名单的联动。

注意事项

  • Linux 以外平台会退化为 no-op。
  • 队列满时会丢 side effect,不阻塞 DNS 主路径。

nftset

作用

把响应 IP 写入 Linux nftables set

参数

结构化写法:

- tag: nftset_main
type: nftset
args:
ipv4:
table_family: "ip"
table_name: "mangle"
set_name: "dns_v4"
mask: 24
ipv6:
table_family: "ip6"
table_name: "mangle"
set_name: "dns_v6"
mask: 64

兼容写法:

args:
table_family4: "ip"
table_name4: "mangle"
set_name4: "dns_v4"
mask4: 24

配置项详解

ipv4

  • 类型:object;必填:否;默认值:无
  • 作用:定义 IPv4 目标 nftables set。
  • 子字段:
    • table_family
    • table_name
    • set_name
    • mask

ipv6

  • 类型:object;必填:否;默认值:无
  • 作用:定义 IPv6 目标 nftables set。
  • 子字段:
    • table_family
    • table_name
    • set_name
    • mask

table_family4 / table_family6

  • 类型:string;必填:否;默认值:无
  • 作用:兼容写法下分别定义 IPv4 / IPv6 的 nftables 表 family。

table_name4 / table_name6

  • 类型:string;必填:否;默认值:无
  • 作用:兼容写法下分别定义 IPv4 / IPv6 的 nftables 表名。

set_name4 / set_name6

  • 类型:string;必填:否;默认值:无
  • 作用:兼容写法下分别定义 IPv4 / IPv6 的 set 名称。

mask4 / mask6

  • 类型:integer;必填:否;默认值:由实现确定
  • 作用:兼容写法下分别定义 IPv4 / IPv6 前缀长度。

quick setup

- exec: "nftset ip,mangle,dns_v4,ipv4_addr,24 ip6,mangle,dns_v6,ipv6_addr,64"

格式:

<family>,<table>,<set>,<type>,<mask>

行为说明

  • 提取 A/AAAA 地址。
  • 根据前缀写入 nftables 区间元素。
  • 同样走后台 writer,保持主路径非阻塞。

典型用途

  • nftables 集合联动的分类、路由或防火墙策略。

注意事项

  • Linux 以外平台退化为 no-op。

mikrotik

作用

把应答 IP 同步到 RouterOS address-list,支持动态项、常驻项、文件重载和关闭时清理。

参数

- tag: mikrotik_main
type: mikrotik
args:
address: "172.16.1.1:8728"
username: "api-user"
password: "secret"
async: true
address_list4: "forgedns_ipv4"
address_list6: "forgedns_ipv6"
comment_prefix: "forgedns"
min_ttl: 60
max_ttl: 3600
fixed_ttl: 300
cleanup_on_shutdown: true
persistent:
ips:
- "1.1.1.1"
- "100.64.1.0/24"
- "2001:db8::/64"
files:
- "/etc/forgedns/persistent_ips.txt"

配置项详解

address

  • 类型:string;必填:是;默认值:无
  • 作用:指定 RouterOS API 服务地址,通常写为 host:port。插件启动后将使用该地址建立管理连接,并在运行期间维持与设备的同步关系。
  • 配置建议:使用 RouterOS API 明文端口时通常为 8728,如部署了加密 API,应按实际端口填写。

username

  • 类型:string;必填:是;默认值:无
  • 作用:指定 RouterOS API 登录用户名。该账户需要具备读取和维护目标 address-list 的权限。
  • 配置建议:建议为本插件单独创建专用账号,以便隔离权限范围和审计记录。

password

  • 类型:string;必填:是;默认值:无
  • 作用:指定 RouterOS API 登录密码。插件初始化、重连和后台同步均依赖该凭据。
  • 注意事项:应避免在公开仓库或共享示例中直接暴露真实口令。

async

  • 类型:bool;必填:否;默认值:true
  • 作用:控制地址写入行为是否采用异步方式。启用后,DNS 应答路径只负责投递任务,由后台管理器完成与 RouterOS 的交互。
  • 影响:异步模式有助于降低请求路径阻塞风险;关闭后会改为同步提交,更适合需要立即确认提交结果的场景。

address_list4

  • 类型:string;必填:否;默认值:无
  • 作用:指定 IPv4 地址写入的目标 address-list 名称。插件从 DNS 应答中提取到 A 记录后,将写入该列表。
  • 配置建议:如果策略仅处理 IPv4,应至少配置本项。

address_list6

  • 类型:string;必填:否;默认值:无
  • 作用:指定 IPv6 地址写入的目标 address-list 名称。插件从 DNS 应答中提取到 AAAA 记录后,将写入该列表。
  • 配置建议:如果策略需要覆盖 IPv6,应同时配置本项,并在 RouterOS 侧建立对应的匹配与路由规则。

comment_prefix

  • 类型:string;必填:否;默认值:fdns
  • 作用:指定插件写入 RouterOS 条目时使用的注释前缀。该前缀用于区分 ForgeDNS 创建的动态项和常驻项,便于后续刷新、重载与清理。
  • 注意事项:该值及插件 tag 不应包含 ;=,以避免影响内部标记格式。

persistent

  • 类型:object;必填:否;默认值:无
  • 作用:定义需要长期保留的静态地址集合。该部分不依赖 DNS 应答触发,可在插件启动后直接同步到 RouterOS,并按周期维持一致性。
  • 子字段:
    • ips
    • files

persistent.ips

  • 类型:array<string>;必填:否;默认值:空
  • 作用:以内联方式声明常驻 IP 或 CIDR 网段。适用于数量较少且变更频率不高的固定策略对象。
  • 支持格式:单个 IPv4、单个 IPv6、IPv4 CIDR、IPv6 CIDR。

persistent.files

  • 类型:array<string>;必填:否;默认值:空
  • 作用:从外部文件加载常驻地址集合。适用于需要由其他系统生成、集中维护或批量管理的地址列表。
  • 行为说明:插件会定期重载这些文件,并将最新内容与 RouterOS 当前状态对齐。

min_ttl

  • 类型:u64;必填:否;默认值:60
  • 作用:定义动态地址项允许使用的最小 TTL。当 DNS 应答中的 TTL 过小或为零时,插件会提升到该值后再写入 RouterOS。
  • 适用场景:用于避免高频刷新造成的管理面抖动。

max_ttl

  • 类型:u64;必填:否;默认值:3600
  • 作用:定义动态地址项允许使用的最大 TTL。当 DNS 应答中的 TTL 过大时,插件会截断到该上限。
  • 适用场景:用于限制策略项在网络设备中的滞留时间,降低地址陈旧风险。

fixed_ttl

  • 类型:u64;必填:否;默认值:无
  • 作用:为所有动态写入项指定固定 TTL。配置本项后,插件不再使用 DNS 记录中的原始 TTL,也不再受 min_ttlmax_ttl 的区间裁剪影响。
  • 适用场景:适合需要统一刷新周期、便于运维预估和策略收敛的场景。

cleanup_on_shutdown

  • 类型:bool;必填:否;默认值:true
  • 作用:控制插件退出时是否清理由其管理的条目。启用后,插件在正常关闭阶段会删除自身写入并可识别归属的 RouterOS 地址项。
  • 影响:关闭该选项后,已写入条目会继续保留在 RouterOS 中,适合要求策略状态跨进程重启保留的场景。

行为说明

  • 插件本身不改 DNS 响应。
  • 正向阶段只透传。
  • 回程阶段:
    • NOERROR 响应中提取 A/AAAA。
    • 去重并保留最大 TTL。
    • 根据异步或同步模式投递给后台 manager。
  • manager 负责:
    • 初始连通性验证
    • 动态项刷新
    • 持久项一致性维护
    • 文件周期重载
    • 关闭清理

典型用途

  • DNS 驱动路由地址集维护。
  • DNS 驱动动态策略名单。
  • 通过 RouterOS address-list 把域名解析结果外溢到网络设备策略层。

注意事项

  • 至少需要 address_list4address_list6 之一。
  • comment_prefix 与插件 tag 不能包含 ;=
  • 同步模式不会改变 DNS 应答本身,即使 RouterOS 写入失败也会保留 DNS 结果。