跳到主要内容

解析与请求处理

这些执行器负责上游解析、缓存、本地应答、请求改写和 EDNS 信息传递。

forward

作用

向上游发起 DNS 查询。

配置示例

- tag: forward_main
type: forward
args:
# 多上游模式下实际并发扇出
concurrent: 3
# 并发上游结果选择模式:fastest / balanced / prefer_positive / consensus
response_selection: balanced
upstreams:
# 最简单的 UDP 上游
- tag: "cf_udp"
addr: "udp://1.1.1.1:53"
timeout: 3s

# 域名型 DoH 上游,演示 bootstrap / 连接池 / HTTP/3 / Linux socket 参数
- tag: "doh_main"
addr: "https://resolver.example/dns-query"
bootstrap: "8.8.8.8:53"
bootstrap_version: 4
port: 443
idle_timeout: 30
min_conns: 2
max_conns: 256
timeout: 5s
enable_pipeline: false
enable_http3: true
so_mark: 100
bind_to_device: "eth0"

# DoT 上游,演示 dial_addr / SOCKS5 / TLS 校验开关 / pipeline
- tag: "dot_backup"
addr: "tls://dns.example:853"
dial_addr: "203.0.113.53"
socks5: "user:pass@127.0.0.1:1080"
idle_timeout: 60
min_conns: 1
max_conns: 128
insecure_skip_verify: false
timeout: 4s
enable_pipeline: true

配置项

concurrent

  • 类型:integer;必填:否;默认值:1
  • 取值范围:实际运行时会限制在 1..=32,且不会超过上游数量
  • 作用:定义多上游模式下的并发查询扇出数。
  • 运行影响:
    • 值越大,多上游竞争越积极,但同时会增加上游请求量。
    • 该值只决定本次实际启动的上游数量,不会在收到 CNAME-only 响应后自动顺序尝试尚未启动的上游;concurrent: 1 保持单次上游选择语义。
    • 推荐常规配置使用 2..=8;更高值适合短期观测或明确需要多协议竞速的场景。

response_selection

  • 类型:string;必填:否;默认值:balanced
  • 取值:fastestbalancedprefer_positiveconsensus
  • 作用:定义多上游并发返回不一致时的结果选择策略。
  • 生效范围:仅用于 upstreams 多于一个的竞争式查询。只有一个上游时直接使用单上游转发器,不执行 response selection;多上游配置使用 concurrent: 1 时,每次也只随机启动其中一个上游,不会为了 selection 再查询其他上游。
  • fastest 外,响应会按原始 Question 分类为:
    • 完整正响应(complete positive):请求类型位于原始 QNAME 或其 CNAME 链终点。
    • 不完整别名(incomplete alias):存在 CNAME 链,但没有最终请求类型,也没有 SOA 否定证明。
    • 确定负响应(definitive negative)NXDOMAIN,或者确认请求类型不存在的 NODATA。
    • 其他响应(other):例如 SERVFAILREFUSED、Question 不匹配、无关 Answer、CNAME 环或冲突。
  • 当策略等待到所有已启动上游结束、且没有触发提前返回时,统一按 完整正响应 > 不完整别名 > 确定负响应 > 其他响应 选择;同等级响应以后完成者为准。传输错误不参与响应排名,只有所有上游均未产生 DNS 响应时才导致 forward 失败。
  • 模式说明:
    • fastest:第一个成功返回的 DNS Message 立即胜出,不执行 query-aware 分类。这里的“成功”只表示上游返回了 DNS Message,因此 NXDOMAINSERVFAILREFUSED 或 CNAME-only 都可能胜出;传输错误不会胜出。
    • balanced:默认模式。完整正响应立即胜出。第一个确定负响应会启动固定 100ms 的 grace window,窗口内仍等待完整正响应;窗口到期或全部上游完成后按上述统一排名选择。不完整别名和其他响应本身不会启动 grace window。
    • prefer_positive:完整正响应立即胜出;否则等待所有已启动上游完成,再按统一排名选择。因此在没有完整正响应时,不完整别名会优先于单个负响应。
    • consensus:完整正响应仍由一票立即胜出。NXDOMAIN 与 NODATA 分开计票,两个同类负响应可提前确认并返回对应负响应;不要求两个负响应的 SOA 或完整报文完全相同。若并发数小于 2,则退化为 prefer_positive。如果所有上游结束仍没有负共识,则按统一排名返回最佳可用响应,此时仍可能返回单个负响应;因此该模式是“负向谨慎”,不是严格的全响应多数决。

CNAME 响应处理

  • 对 A/AAAA 等非 CNAME 查询,只有最终请求类型位于原始 QNAME 的 CNAME 链尾时,才视为完整正向答案。
  • 仅含 CNAME、且没有最终请求类型和 SOA 的响应属于 incomplete alias:不会提前胜出、不会计入负响应共识,但当没有更好结果时仍会原样返回。
  • CNAME + SOA 且没有最终请求类型会识别为 NODATA;NXDOMAIN 即使带有 CNAME 也仍是负响应。
  • forward 不执行隐藏式 fallback 或 CNAME chase;需要更多上游竞争时请显式提高 concurrent
  • fallback executor 只判断分支是否产生了 response,不理解 response disposition;incomplete alias 或 SERVFAIL Message 也会被视为成功响应。若希望这些结果显式触发另一个上游,应使用 has_wanted_ansrcode 等 matcher 组合 sequence,而不是依赖隐藏式 fallback。

upstreams

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

short_circuit

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制在拿到成功上游响应后,是否立即停止后续 executor 链。
  • 说明:
    • 关闭时,forward 仍会写入 response,但后续 executor 还能继续处理这份响应。
    • 开启时,只要 selection 选出了 DNS Message 就会直接结束后续 executor 链;这也包括作为最佳可用结果返回的 incomplete alias、SERVFAILREFUSED

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
  • 解析行为:启动和配置校验阶段不会解析域名型上游;未配置 bootstrapdial_addr 时,会在首次建连时使用系统解析。
  • 配置建议:域名型上游建议在 bootstrapdial_addr 中二选一,避免运行期形成对本机 DNS 的引导解析依赖。
  • 互斥规则:bootstrapdial_addr 同时配置时,只有 dial_addr 生效,bootstrap 会被忽略。

upstreams[].tag

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

upstreams[].dial_addr

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

upstreams[].outbound

  • 类型:string;必填:否
  • 作用:引用 network.outbound.profiles 中的出站配置,为该上游注入 resolver 和 proxy。
  • 默认:未配置时使用 network.outbound.default;没有 default 时保持系统解析/直连。
  • 覆盖规则:本地 dial_addr 优先于 resolver;本地 bootstrap 优先于 outbound resolver;本地 socks5 优先于 profile proxy。
  • 注意:profile proxy 只应用于 TCP、DoT 和 DoH2;UDP、DoQ、DoH3 upstream 会忽略 SOCKS5 proxy。

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 域名上游的首次解析。
    • 使用 bootstrap 后,上游域名解析由 OxiDNS 查询该引导服务器完成,并按 TTL 缓存。
    • dial_addr 同时配置时,本字段会被忽略。

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@...
    • SOCKS5 只应用于 TCP、DoT 和 DoH2;UDP、DoQ、DoH3 upstream 会忽略该设置。
  • 注意事项:格式错误、端口非法或代理主机解析失败时,该上游不会被正常创建。

upstreams[].idle_timeout

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

upstreams[].max_conns

  • 类型:integer;必填:否;默认值:64
  • 作用:定义连接池连接上限。
  • 取值范围:1..4096
  • 示例:max_conns: 256

upstreams[].min_conns

  • 类型:integer;必填:否;默认值:0
  • 作用:定义连接池保持预热的最小连接数。
  • 取值范围:0..4096,且不能大于当前上游的有效 max_conns
  • 说明:未配置时保持懒加载,不会在启动或 pool 创建时主动预建连接。
  • 示例:min_conns: 2

upstreams[].insecure_skip_verify

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

upstreams[].timeout

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

upstreams[].enable_pipeline

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制 TCP 或 DoT 流水线。
  • 示例:enable_pipeline: true
  • 说明:也可直接通过 tcp+pipeline://tls+pipeline://addr 中启用。
  • 建议:开启前先用 oxidns probe upstream <addr> 探测目标上游。该命令会对 TCP/DoT 强制同一条连接并发查询,帮助判断该上游是否适合启用 pipeline,避免遇到超时、连接关闭、响应 ID 错乱或 question 串线。
  • 判定:探测结果为 supported 时再考虑开启;如果为 unsupportedunstableinconclusive,建议保持关闭,或降低并发 / 延长超时后重新测试。

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"
- exec: "forward 1.1.1.1 short_circuit=true"

说明:

  • 单个地址创建单上游转发。
  • 多个地址创建并发竞争转发。
  • quick setup 支持尾部开关 short_circuitshort_circuit=trueshort_circuit=false
  • 其它进阶参数需要完整插件形式。

行为说明

  • 单上游模式:直接查询该上游。
  • 多上游模式:从随机起点选择上游并发查询,先返回成功结果者胜出。
  • 开启 short_circuit 时,一旦拿到可用上游响应,就会立即停止后续 executor 链。

Metrics

通过全局 GET /api/metrics 导出:

  • forward_query_total
  • forward_success_total
  • forward_error_total
  • forward_timeout_total
  • forward_incomplete_alias_selected_total
  • forward_latency_count
  • forward_latency_sum_ms

forward_incomplete_alias_selected_total 仅统计执行语义分类的并发选择模式(balancedprefer_positiveconsensus)。单上游和 fastest 不会为了该指标额外扫描响应。

每个上游另外导出带 upstream 标签的指标(标签值为上游 tag,未配置时为解析后的地址):

  • forward_upstream_query_total
  • forward_upstream_success_total
  • forward_upstream_error_total
  • forward_upstream_timeout_total
  • forward_upstream_latency_count
  • forward_upstream_latency_sum_ms

常见用途

  • 标准转发。
  • 多上游容错。
  • 多协议混合上游。
注意事项
  • 需要更细的并发、代理、引导解析、HTTP/3 参数时,使用完整 upstreams 配置。
  • 多上游越多并不一定越好,先保证上游分组语义清晰。

cache

作用

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

对 A/AAAA 等非 CNAME 查询,cache 仅缓存位于原始 QNAME/CNAME 链尾的完整请求类型答案,并校验响应 Question 的 QNAME/QTYPE/QCLASS 与缓存 key 一致。裸 CNAME 响应不会写入该地址查询 key;带 SOA 的 CNAME + NODATA 会写入负缓存,其寿命取 SOA negative TTL、CNAME 等 Answer 最小 TTL 与配置上限中的最小值。

配置示例

- tag: cache_main
type: cache
args:
# 最大缓存条目数
size: 8192
# 命中缓存后直接结束后续执行
short_circuit: true
# 允许在原始 TTL 过期后短时间返回 stale 响应,并异步刷新缓存
lazy_cache_ttl: 120
# 开启 NXDOMAIN / NODATA 负缓存
cache_negative: true
# 负缓存 TTL 上限
max_negative_ttl: 300
# 负响应没有 SOA 时使用的回退 TTL
negative_ttl_without_soa: 60
# 正响应 TTL 上限
max_positive_ttl: 600
# 正响应进入缓存所需的最小 TTL
min_positive_ttl: 4
# ECS 不参与缓存键,提升命中率
ecs_in_key: false
# 启用缓存持久化
dump_file: "./dns_cache.dump"
# 定期落盘周期,单位秒
dump_interval: 600

配置项

size

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

lazy_cache_ttl

  • 类型:integer;必填:否;默认值:无
  • 单位:秒
  • 作用:为正向成功响应启用 lazy cache。
  • 运行影响:
    • 原始 TTL 决定 fresh 命中窗口。
    • lazy_cache_ttl 决定 stale 回包 TTL,并允许在原始 TTL 过期后短时间返回 stale 响应。
    • stale 命中会在后台异步刷新缓存。
    • 该配置不会缩短原始 fresh TTL。

dump_file

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

dump_interval

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

short_circuit

  • 类型:boolean;必填:否;默认值:false
  • 作用:控制缓存命中后是否立即结束后续执行。
  • 说明:
    • 设为 false 时,即使 cache 已经写入 response,后续执行链仍会继续。
    • 如需避免后续 forward 再次发起查询,应在 sequence 中配合 has_respaccept 等控制流使用。

cache_negative

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

max_negative_ttl

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

negative_ttl_without_soa

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

max_positive_ttl

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

min_positive_ttl

  • 类型:integer;必填:否;默认值:无
  • 单位:秒
  • 作用:定义正响应进入缓存所需的最小 TTL。
  • 说明:正响应的有效缓存 TTL 低于该值时不会写入缓存。该判断在 max_positive_ttl 裁剪之后执行。

ecs_in_key

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

quick setup

- exec: "cache"
- exec: "cache short_circuit=true"

说明:

  • 不带参数时使用默认缓存配置。
  • 目前 quick setup 支持尾部开关 short_circuitshort_circuit=trueshort_circuit=false
  • 其它高级参数仍建议使用完整插件形式。

行为说明

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

插件 API

  • GET /plugins/<tag>/entries
    • 分页读取缓存项;支持 limitcursorqname 查询参数,其中 qname 按缓存键域名做大小写不敏感的包含筛选。
  • GET /plugins/<tag>/flush
    • 清空缓存。
  • GET /plugins/<tag>/dump
    • 导出缓存内容。
  • POST /plugins/<tag>/load_dump
    • 导入缓存 dump。

Metrics

通过全局 GET /api/metrics 导出,不提供 cache 专属 stats/metrics 接口。

  • cache_lookup_total
  • cache_hit_total{kind="fresh|stale"}
  • cache_miss_total
  • cache_expired_total
  • cache_insert_total
  • cache_skip_total{reason="truncated|no_ttl|incomplete_answer|low_positive_ttl"}
  • cache_lazy_refresh_total{result="started|success|failed"}
  • cache_entry_count

典型用途

  • 所有转发入口前置缓存。
  • 构建高命中率低时延策略。
  • 在可控场景中持久化缓存,加快重启后恢复。
注意事项
  • 如果前面有会直接生成本地应答的插件,放置位置会决定这些结果是否进入缓存。
  • ecs_in_key 开启后,缓存碎片会明显增加。

hosts

作用

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

配置示例

- tag: hosts_main
type: hosts
args:
entries:
# 无前缀规则默认按 full: 处理
- "router.local 192.168.1.1"
# 精确匹配单个主机名
- "full:gateway.local 192.168.1.2"
# 后缀匹配,可同时返回 IPv4 / IPv6
- "domain:svc.local 10.0.0.10 fd00::10"
# 关键字匹配
- "keyword:nas 192.168.1.20"
# 正则匹配
- "regexp:^api[0-9]+\\.corp\\.local$ 10.10.0.5"
files:
# 从文件合并更多 hosts 规则
- "/etc/oxidns/hosts.txt"
short_circuit: true

配置项

entries

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

files

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

short_circuit

  • 类型:bool;必填:否;默认值:false
  • 作用:命中并生成本地应答后,是否立即停止后续 executor 链。

行为说明

  • 仅处理“恰好一个 question”的 INA / AAAA 请求。
  • 无前缀规则默认等价于 full:,与 mosdns hosts 保持一致。
  • 规则优先级固定为 full -> domain -> regexp -> keyword
  • domain: 按最长后缀命中。
  • 相同 pattern 按加载顺序后写覆盖前写;加载顺序为 entries 先,再按 files 顺序逐文件逐行覆盖。
  • 根据查询类型返回同族地址,正向本地答案 TTL 固定为 10
  • 域名命中但请求家族没有对应地址时,返回 NoError + 空 Answer + fake SOA,不会透传后续执行。
  • 未命中时透传后续执行。
  • 命中后默认继续后续执行;开启 short_circuit 时,无论是正向答案还是空本地答复,都会立即停止后续 executor 链。

Metrics

通过全局 GET /api/metrics 导出:

  • hosts_hit_total
  • hosts_miss_total

典型用途

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

arbitrary

作用

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

配置示例

- tag: arbitrary_main
type: arbitrary
args:
rules:
# TXT 记录
- "example.com. 60 IN TXT \"hello world\""
# MX 记录
- "mail.example.com. 300 IN MX 10 mx1.example.com."
# A / AAAA / CNAME / PTR 也都可以直接写
- "www.example.com. 120 IN A 192.0.2.10"
- "www.example.com. 120 IN AAAA 2001:db8::10"
- "alias.example.com. 120 IN CNAME www.example.com."
- "10.2.0.192.in-addr.arpa. 300 IN PTR host.example.com."
files:
# 从文件加载更多静态记录
- "/etc/oxidns/zone.txt"
short_circuit: false

配置项

rules

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义内联静态记录列表。
  • 语法:
    • 每个数组项会作为独立 zone 片段解析。
    • 支持 $ORIGIN$TTL$INCLUDE$GENERATE、owner 继承、TTL 单位写法、注释、quoted string、多行 ( ) 语法。
    • 常见记录类型支持直接文本解析,包括 AAAAACNAMENSPTRDNAMEANAMEMDMFMBMGMRNSAPPTRMXRTAFSDBRPMINFOHINFOTXTSPFAVCRESINFOSOASRVNAPTRCAA
    • 其他记录类型可通过 RFC3597 通用语法 TYPE#### \# <len> <hex> 导入。
    • 省略 TTL 时默认使用 3600

files

  • 类型:array;必填:否;默认值:空数组
  • 作用:指定静态记录文件列表。
  • 语法:使用同一套 zone parser,支持与 rules 一致的语法能力。

short_circuit

  • 类型:bool;必填:否;默认值:false
  • 作用:命中并生成本地响应后,是否立即停止后续 executor 链。
  • 说明:默认只设置 response 并继续执行;显式开启时返回 Stop

行为说明

  • qname + qtype + qclass 精确匹配。
  • 一个请求里如果有多个 question,会把所有命中的记录按顺序累积到同一个响应中。
  • 命中后默认只设置 response,不会中断后续 executor 链。
  • 开启 short_circuit 时,命中后会立即结束后续 executor 链。
  • 不提供 quick setup 语法。

典型用途

  • 少量静态权威式记录。
  • 本地 TXT / MX / PTR / CNAME 数据。
  • 测试或实验环境的本地响应。
注意事项
  • 这是“静态响应生成器”,不负责 zone 传送、动态更新或权威服务器完整语义。
  • 解析器能力比 mosdns arbitrary 使用的 zone parser 更宽,但命中行为仍是静态记录的精确匹配。

response

作用

无条件构造并覆盖当前 DNS 响应。它适合策略性返回固定答案、带 SOA 的 NODATA、或需要同时控制 Answer、Authority 和 Additional 的响应;调用条件由外层 sequence 的 matcher 决定。

配置示例

- tag: suppress_https
type: response
args:
rcode: NOERROR
# HTTPS/SVCB 查询可由 sequence 的 qtype matcher 调用此插件
answers: []
authorities:
- "{qname} 300 {qclass} SOA fake-ns.oxidns.fake.root. fake-mbox.oxidns.fake.root. 2021110400 1800 900 604800 300"
additionals: []
short_circuit: true

带 Answer 和 Additional 的例子:

args:
rcode: NOERROR
answers:
- "{qname} 60 {qclass} CNAME target.example.com."
additionals:
- "target.example.com. 60 IN A 192.0.2.10"
authoritative: true

配置项

rcode

  • 类型:stringnumber;必填:否;默认值:NOERROR
  • 支持十进制基础 RCODE 0..15 和大小写不敏感的助记名,例如 NXDOMAIN
  • 不支持需要 EDNS 表达的扩展 RCODE。

answers / authorities / additionals

  • 类型:array;必填:否;默认值:空数组
  • 每项必须恰好是一条 zone 风格资源记录,格式为 <owner> <ttl> <class> <type> <rdata>
  • {qname} 只能作为 owner,替换为首个 request question 的名称;{qclass} 只能作为 class,替换为该 question 的类别。
  • SOA 应放在 authorities。SOA TTL 和 RDATA 中的 minimum 共同决定负缓存时间。

authoritative / authentic_data

  • 类型:bool;必填:否;默认值:false
  • 分别控制 AA 和 AD 响应标志。RA 由 server 统一处理,RD/CD 和 Question 从 request 继承。

short_circuit

  • 类型:bool;必填:否;默认值:true
  • true 时设置响应后停止当前 executor 链;关闭后继续执行后续规则。

行为说明

  • 每次执行都会从当前 request 构建新响应,覆盖已有 response,不会按 qtype 筛选或合并已有记录。
  • 配置中的记录在启动时解析;请求路径只克隆记录并解析占位符。
  • 没有 Question 的请求若使用 {qname}{qclass} 会失败。
  • 不提供 quick setup 或文件加载;按 qname + qtype + qclass 加载静态记录的场景应使用 arbitrary

典型用途

  • 为选定 qtype 返回带 SOA 的 NODATA。
  • 策略性返回固定 A、AAAA、TXT、CNAME 或 MX 响应。
  • 构造含 Answer、Authority 和 Additional 的本地测试响应。

redirect

作用

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

配置示例

- tag: redirect_main
type: redirect
args:
rules:
# 精确重定向
- "full:old.example.com new.example.net"
# 后缀重定向
- "domain:legacy.example.com modern.example.net"
# 关键字重定向
- "keyword:staging staging-gateway.example.net"
# 正则重定向
- "regexp:^api[0-9]+\\.legacy\\.example\\.com$ api-gateway.example.net"
# 无前缀规则默认按 full: 处理
- "old-static.example.com static.example.net"
files:
# 从文件合并更多重定向规则
- "/etc/oxidns/redirect.txt"

配置项

rules

  • 类型:array;必填:否;默认值:空数组
  • 作用:定义内联重定向规则。
  • 规则格式:
    • <域名规则> <目标域名>
  • <域名规则> 支持:
    • full:
    • domain:
    • keyword:
    • regexp:
    • 无前缀域名(按 full: 精确匹配处理)

files

  • 类型:array;必填:否;默认值:空数组
  • 作用:指定外部重定向规则文件列表。
  • 文件格式与 rules 相同,每行一条;空行和 # 注释会被忽略。

规则格式:

full:old.example.com new.example.net
domain:legacy.example.com modern.example.net
keyword:staging staging-gateway.example.net
regexp:^api[0-9]+\.legacy\.example\.com$ api-gateway.example.net
old-static.example.com static.example.net

行为说明

  • 仅处理 IN 类请求;没有 question 或未命中时透传后续 executor。
  • 多条规则同时命中时,按加载顺序最先出现的规则生效;加载顺序为 rules 先,再按 files 顺序逐文件逐行加载。
  • redirect 本身不解析目标域名,需要在 sequence 中配合 forward 等后续 executor 使用,由后续 executor 生成目标域名的真实响应。
  • 正向阶段:改写请求的 QUESTION NAME。
  • 回程阶段:
    • 把 response question 中的目标名还原为原始名。
    • 在 answers 开头插入一条 CNAME original -> target

常见 sequence 用法:

- exec: "$redirect_main"
- exec: "$forward_main"

典型用途

  • 统一入口域名指向另一套记录。
  • 对特定域名做别名跳转而不改客户端配置。
注意事项
  • 通常应把 redirect 放在 forward 之前;如果后续链路没有产生 response,redirect 不会凭空生成目标记录。
  • 更适合 A/AAAA/TXT 这类简单请求。
  • 对复杂记录和某些扩展场景不保证完全语义透明。

client_ip_from_ecs

作用

把请求 EDNS Client Subnet(ECS)中的地址设为当前 DnsContext 的客户端 IP。 这适用于 OxiDNS 位于 dnsmasq 后方、dnsmasq 使用 --add-subnet=32,128 转发完整请求方地址的场景。

配置示例

- tag: ecs_client
type: client_ip_from_ecs
args:
# 只信任本机 dnsmasq
- 127.0.0.1
- ::1
# 也可允许自定义转发网段
- 10.0.0.0/24

- tag: main
type: sequence
args:
# 必须放在依赖客户端 IP 的 matcher、日志或记录器之前
- exec: $ecs_client
- matches: client_ip 192.168.1.0/24
exec: $forward_main

也可在 sequence 中使用 quick setup:

- exec: "client_ip_from_ecs 127.0.0.1"

配置项

args

  • 类型:array[string];必填:否;默认值:[127.0.0.1, ::1]
  • 作用:允许提交 ECS 的原始客户端 IP 或 CIDR 白名单。
  • 支持 IPv4、IPv6、单个 IP 和 CIDR;暂不支持 lan
  • 未配置或空数组时只信任 IPv4/IPv6 loopback;包含非法规则时插件初始化失败。

行为说明

  • 先用未修改的原始连接 IP 检查 args;不命中时忽略 ECS。
  • 来源可信、ECS 存在且 IPv4 source prefix 为 /32 或 IPv6 source prefix 为 /128 时,覆盖客户端 IP,但保留原连接端口。
  • ECS 缺失或 source prefix 不是对应地址族的完整 host prefix 时不做修改。
  • 支持 IPv4 和 IPv6,也会规范化 IPv4-mapped IPv6 地址。
  • 不修改或删除 ECS;如需 ECS 转发/清理,另行配置 ecs_handler
  • 修改仅限当前请求上下文,后续 client_ip matcher、模板和 query recorder 会读取新地址。
信任边界

ECS 可由请求方伪造。请把 dnsmasq 的真实连接地址或网段明确写入 args, 并让 dnsmasq 使用 --strip-subnet 配合 --add-subnet=32,128 替换下游 ECS。 小于 /32/128 的 ECS 只能提供截断后的网段地址,无法还原完整客户端 IP。


ecs_handler

作用

处理 EDNS Client Subnet。

配置示例

- tag: ecs_main
type: ecs_handler
args:
# 客户端自带 ECS 时先移除
forward: false
# 请求没有 ECS 时自动补发
send: true
# IPv4 ECS 前缀长度
mask4: 24
# IPv6 ECS 前缀长度
mask6: 48

- tag: ecs_preset
type: ecs_handler
args:
# 预设 ECS 地址
preset: "203.0.113.10"
# 固定来源模式下也建议显式写出策略开关
forward: false
send: true
mask4: 24
mask6: 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:
# 只透传指定的 EDNS0 option code
codes: [10, 12]

配置项

codes

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

quick setup

- exec: "forward_edns0opt 10,12"

行为说明

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

典型用途

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