解析与请求处理
这些执行器负责上游解析、缓存、本地应答、请求改写和 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 - 取值:
fastest、balanced、prefer_positive、consensus - 作用:定义多上游并发返回不一致时的结果选择策略。
- 生效范围:仅用于
upstreams多于一个的竞争式查询。只有一个上游时直接使用单上游转发器,不执行 response selection;多上游配置使用concurrent: 1时,每次也只随机启动其中一个上游,不会为了 selection 再查询其他上游。 - 除
fastest外,响应会按原始 Question 分类为:- 完整正响应(complete positive):请求类型位于原始 QNAME 或其 CNAME 链终点。
- 不完整别名(incomplete alias):存在 CNAME 链,但没有最终请求类型,也没有 SOA 否定证明。
- 确定负响应(definitive negative):
NXDOMAIN,或者确认请求类型不存在的 NODATA。 - 其他响应(other):例如
SERVFAIL、REFUSED、Question 不匹配、无关 Answer、CNAME 环或冲突。
- 当策略等待到所有已启动上游结束、且没有触发提前返回时,统一按
完整正响应 > 不完整别名 > 确定负响应 > 其他响应选择;同等级响应以后完成者为准。传输错误不参与响应排名,只有所有上游均未产生 DNS 响应时才导致forward失败。 - 模式说明:
fastest:第一个成功返回的 DNS Message 立即胜出,不执行 query-aware 分类。这里的“成功”只表示上游返回了 DNS Message,因此NXDOMAIN、SERVFAIL、REFUSED或 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。fallbackexecutor 只判断分支是否产生了 response,不理解 response disposition;incomplete alias 或SERVFAILMessage 也会被视为成功响应。若希望这些结果显式触发另一个上游,应使用has_wanted_ans、rcode等 matcher 组合 sequence,而不是依赖隐藏式 fallback。
upstreams
- 类型:
array;必填:是;默认值:无 - 作用:定义一个或多个上游目标。
- 运行影响:
- 数组长度为
1时使用单上游模式。 - 数组长度大于
1时使用竞争式查询模式。
- 数组长度为
short_circuit
- 类型:
boolean;必填:否;默认值:false - 作用:控制在拿到成功上游响应后,是否立即停止后续 executor 链。
- 说明:
- 关闭时,
forward仍会写入response,但后续 executor 还能继续处理这份响应。 - 开启时,只要 selection 选出了 DNS Message 就会直接结束后续 executor 链;这也包括作为最佳可用结果返回的 incomplete alias、
SERVFAIL或REFUSED。
- 关闭时,
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:53或8.8.8.8:53tcp://8.8.8.8:53tcp+pipeline://8.8.8.8:53tls://dns.example:853tls+pipeline://dns.example:853quic://dns.example:853或doq://dns.example:853https://resolver.example/dns-query或doh://resolver.example/dns-queryh3://resolver.example/dns-query
- 规则说明:
- 未写协议时,按
udp://处理。 https:///doh://表示 DoH,h3://表示强制 DoH over HTTP/3。tcp+pipeline://与tls+pipeline://会直接启用流水线模式。- DoH 地址应包含实际请求路径,例如
/dns-query。
- 未写协议时,按
- 解析行为:启动和配置校验阶段不会解析域名型上游;未配置
bootstrap或dial_addr时,会在首次建连时使用系统解析。 - 配置建议:域名型上游建议在
bootstrap和dial_addr中二选一,避免运行期形成对本机 DNS 的引导解析依赖。 - 互斥规则:
bootstrap和dial_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: 4bootstrap_version: 6
- 取值:
4或6。
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:portusername: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时再考虑开启;如果为unsupported、unstable或inconclusive,建议保持关闭,或降低并发 / 延长超时后重新测试。
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_circuit、short_circuit=true、short_circuit=false。 - 其它进阶参数需要完整插件形式。
行为说明
- 单上游模式:直接查询该上游。
- 多上游模式:从随机起点选择上游并发查询,先返回成功结果者胜出。
- 开启
short_circuit时,一旦拿到可用上游响应,就会立即停止后续 executor 链。
Metrics
通过全局 GET /api/metrics 导出:
forward_query_totalforward_success_totalforward_error_totalforward_timeout_totalforward_incomplete_alias_selected_totalforward_latency_countforward_latency_sum_ms
forward_incomplete_alias_selected_total 仅统计执行语义分类的并发选择模式(balanced、prefer_positive、consensus)。单上游和 fastest 不会为了该指标额外扫描响应。
每个上游另外导出带 upstream 标签的指标(标签值为上游 tag,未配置时为解析后的地址):
forward_upstream_query_totalforward_upstream_success_totalforward_upstream_error_totalforward_upstream_timeout_totalforward_upstream_latency_countforward_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_resp、accept等控制流使用。
- 设为
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_circuit、short_circuit=true、short_circuit=false。 - 其它高级参数仍建议使用完整插件形式。
行为说明
- 既会读缓存,也会在后续拿到响应后写缓存。
- 命中缓存时,返回缓存副本并按剩余 TTL 输出。
- 内置过期清理和近似 LRU 回收。
插件 API
GET /plugins/<tag>/entries- 分页读取缓存项;支持
limit、cursor和qname查询参数,其中qname按缓存键域名做大小写不敏感的包含筛选。
- 分页读取缓存项;支持
GET /plugins/<tag>/flush- 清空缓存。
GET /plugins/<tag>/dump- 导出缓存内容。
POST /plugins/<tag>/load_dump- 导入缓存 dump。
Metrics
通过全局 GET /api/metrics 导出,不提供 cache 专属 stats/metrics 接口。
cache_lookup_totalcache_hit_total{kind="fresh|stale"}cache_miss_totalcache_expired_totalcache_insert_totalcache_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”的
IN类A/AAAA请求。 - 无前缀规则默认等价于
full:,与 mosdnshosts保持一致。 - 规则优先级固定为
full -> domain -> regexp -> keyword。 domain:按最长后缀命中。- 相同 pattern 按加载顺序后写覆盖前写;加载顺序为
entries先,再按files顺序逐文件逐行覆盖。 - 根据查询类型返回同族地址,正向本地答案 TTL 固定为
10。 - 域名命中但请求家族没有对应地址时,返回
NoError + 空 Answer + fake SOA,不会透传后续执行。 - 未命中时透传后续执行。
- 命中后默认继续后续执行;开启
short_circuit时,无论是正向答案还是空本地答复,都会立即停止后续 executor 链。
Metrics
通过全局 GET /api/metrics 导出:
hosts_hit_totalhosts_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、多行()语法。 - 常见记录类型支持直接文本解析,包括
A、AAAA、CNAME、NS、PTR、DNAME、ANAME、MD、MF、MB、MG、MR、NSAPPTR、MX、RT、AFSDB、RP、MINFO、HINFO、TXT、SPF、AVC、RESINFO、SOA、SRV、NAPTR、CAA。 - 其他记录类型可通过 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
- 类型:
string或number;必填:否;默认值: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_ipmatcher、模板和 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最大32,mask6最大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 扩展。
- 在策略链中保留与下游会话有关的附加元数据。