常见策略场景
本章提供常见部署需求对应的配置示例。可以先从“最小可运行 DNS 网关”启动服务,再按需要加入家庭网关、域名分流、上游容错、加密上游、规则订阅、审计排障或网络联动能力。
每个示例都可以作为一份独立配置或策略片段使用。没有写 udp_server / tcp_server 的示例,表示重点在策略链本身;实际部署时可把对应 seq_main 接入“最小可运行 DNS 网关”里的监听器。
场景一:最小可运行 DNS 网关
策略目标:
- 提供 UDP / TCP 两种标准 DNS 入口
- 本地 hosts 优先,未命中再走缓存和公共上游
- 使用非特权端口,方便先在本机或容器中验证
api:
http: "127.0.0.1:9088"
plugins:
- tag: local_hosts
type: hosts
args:
entries:
- "full:router.lan 192.168.1.1"
- "domain:svc.lan 192.168.10.10 fd00::10"
short_circuit: true
- tag: cache_main
type: cache
args:
size: 4096
short_circuit: true
cache_negative: true
- tag: forward_main
type: forward
args:
upstreams:
- addr: "udp://1.1.1.1:53"
- tag: seq_main
type: sequence
args:
- exec: "$local_hosts"
- exec: "$cache_main"
- matches: "!has_resp"
exec: "$forward_main"
- tag: udp_lan
type: udp_server
args:
entry: "seq_main"
listen: ":5353"
- tag: tcp_lan
type: tcp_server
args:
entry: "seq_main"
listen: ":5353"
适用场景:
- 首次验证 OxiDNS 行为
- 家庭或实验网络的起步配置
- 需要先避开
:53端口权限、端口占用和系统 DNS 冲突
场景二:家庭或小办公室一体化策略
策略目标:
- 本地域名优先返回
- 广告规则命中后返回黑洞应答
- 未命中流量走缓存和公共上游
- 提供指标入口,便于后续接入观测
api:
http:
listen: "127.0.0.1:9088"
auth:
type: basic
username: "admin"
password: "secret"
plugins:
- tag: metrics_main
type: metrics_collector
args:
name: "home"
- tag: local_hosts
type: hosts
args:
entries:
- "full:router.lan 192.168.1.1"
- "full:nas.lan 192.168.1.20"
- "domain:svc.lan 192.168.10.10"
short_circuit: true
- tag: ad_rules
type: adguard_rule
args:
rules:
- "||ads.example.com^"
- "||tracking.example.net^"
- "@@||safe.ads.example.com^"
- tag: blocked
type: sequence
args:
- exec: "black_hole 0.0.0.0 ::"
- exec: accept
- tag: cache_main
type: cache
args:
size: 8192
short_circuit: true
cache_negative: true
- tag: forward_main
type: forward
args:
upstreams:
- addr: "udp://1.1.1.1:53"
- addr: "udp://8.8.8.8:53"
- tag: seq_main
type: sequence
args:
- exec: "$metrics_main"
- exec: "$local_hosts"
- matches: "question $ad_rules"
exec: goto blocked
- exec: "$cache_main"
- matches: "!has_resp"
exec: "$forward_main"
- tag: udp_lan
type: udp_server
args:
entry: "seq_main"
listen: ":5353"
- tag: tcp_lan
type: tcp_server
args:
entry: "seq_main"
listen: ":5353"
适用场景:
- 家用网关、旁路 DNS 或小办公室 DNS
- 希望一份配置同时处理本地名称、广告过滤、缓存和默认转发
- 先用内联规则起步,再逐步切换到外部规则文件
场景三:按域名分流到不同上游
策略目标:
- 内部域名走内网 DNS
- 指定域名走专用上游
- 其它请求走默认上游
plugins:
- tag: internal_domains
type: domain_set
args:
exps:
- "domain:corp.lan"
- "domain:internal.example"
- tag: privacy_domains
type: domain_set
args:
exps:
- "domain:example.org"
- "full:secure.example.net"
- tag: forward_internal
type: forward
args:
upstreams:
- addr: "udp://192.168.1.1:53"
- tag: forward_privacy
type: forward
args:
upstreams:
- addr: "tls://dns.quad9.net:853"
bootstrap: "9.9.9.9:53"
- tag: forward_default
type: forward
args:
upstreams:
- addr: "udp://1.1.1.1:53"
- tag: seq_main
type: sequence
args:
- matches: "qname $internal_domains"
exec: "$forward_internal"
- matches: "qname $privacy_domains"
exec: "$forward_privacy"
- matches: "!has_resp"
exec: "$forward_default"
适用场景:
- 公司内网域名和公网域名混合解析
- 只让少量域名使用特定出口或特定加密上游
- 避免把域名列表重复写在多条
sequence规则里
场景四:多上游容错与快速回退
策略目标:
- 优先走延迟更低的主链路
- 主链路慢或失败时快速切换
- 不让备用链路在所有请求上都变成强依赖
plugins:
- tag: forward_fast
type: forward
args:
upstreams:
- addr: "https://cloudflare-dns.com/dns-query"
bootstrap: "1.1.1.1:53"
- tag: forward_stable
type: forward
args:
upstreams:
- addr: "tls://dns.google:853"
bootstrap: "8.8.8.8:53"
- tag: fallback_main
type: fallback
args:
primary: "forward_fast"
secondary: "forward_stable"
threshold: 200
always_standby: false
- tag: seq_main
type: sequence
args:
- exec: "$fallback_main"
适用场景:
- 一条上游追求速度,一条上游追求稳定
- 希望改善尾延迟
- 将容错逻辑收敛在一个 executor 里,而不是在多条规则里重复兜底
场景五:出站使用加密 DNS 上游
策略目标:
- 客户端仍使用普通 UDP / TCP 访问 OxiDNS
- OxiDNS 到上游使用 DoH / DoT
- 多个加密上游之间做并发竞争
plugins:
- tag: cache_main
type: cache
args:
size: 8192
short_circuit: true
cache_negative: true
- tag: forward_encrypted
type: forward
args:
concurrent: 2
upstreams:
- tag: "cloudflare_doh"
addr: "https://cloudflare-dns.com/dns-query"
bootstrap: "1.1.1.1:53"
timeout: 5s
- tag: "google_dot"
addr: "tls://dns.google:853"
bootstrap: "8.8.8.8:53"
timeout: 5s
- tag: seq_main
type: sequence
args:
- exec: "$cache_main"
- matches: "!has_resp"
exec: "$forward_encrypted"
- tag: udp_lan
type: udp_server
args:
entry: "seq_main"
listen: ":5353"
- tag: tcp_lan
type: tcp_server
args:
entry: "seq_main"
listen: ":5353"
适用场景:
- 局域网内保持普通 DNS 接入
- 出站链路希望加密
- 希望用
bootstrap避免域名型上游形成自举依赖
如需对客户端提供 DoT / DoH / DoQ 入口,请在此基础上增加 tcp_server TLS、http_server 或 quic_server 实例,并提前准备可读的证书和私钥文件。
场景六:广告规则订阅自动更新
策略目标:
- 首次启动时自动补齐本地规则文件
- 后台周期性下载规则订阅
- 下载完成后只刷新相关 provider,不全量重载进程
plugins:
- tag: subscription_download
type: download
args:
timeout: 60s
startup_if_missing: true
downloads:
- url: "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt"
dir: "./rules"
filename: "adguard.txt"
- tag: ad_rules
type: adguard_rule
args:
files:
- "./rules/adguard.txt"
- tag: reload_ad_rules
type: reload_provider
args:
- "$ad_rules"
- tag: subscription_refresh
type: sequence
args:
- exec: "$subscription_download"
- exec: "$reload_ad_rules"
- tag: subscription_cron
type: cron
args:
timezone: "Asia/Shanghai"
jobs:
- name: refresh_ad_rules
interval: 12h
executors:
- "$subscription_refresh"
- tag: blocked
type: sequence
args:
- exec: "black_hole 0.0.0.0 ::"
- exec: accept
- tag: cache_main
type: cache
args:
size: 8192
short_circuit: true
cache_negative: true
- tag: forward_main
type: forward
args:
upstreams:
- addr: "udp://1.1.1.1:53"
- tag: seq_main
type: sequence
args:
- matches: "question $ad_rules"
exec: goto blocked
- exec: "$cache_main"
- matches: "!has_resp"
exec: "$forward_main"
适用场景:
- 规则文件来自远程订阅
- 希望规则更新独立于主配置更新
- 不希望把
reload这种全量重载动作放进实时请求路径
场景七:调试、审计与路径分析
策略目标:
- 记录查询摘要和结构化查询历史
- 保留
sequence执行路径,方便排查规则命中 - 同时暴露指标和管理 API
api:
http:
listen: "127.0.0.1:9088"
auth:
type: basic
username: "admin"
password: "secret"
plugins:
- tag: metrics_main
type: metrics_collector
args:
name: "debug"
- tag: recorder_main
type: query_recorder
args:
path: "./query-recorder.sqlite"
queue_size: 8192
batch_size: 256
flush_interval_ms: 200
memory_tail: 1024
retention_days: 7
- tag: summary_main
type: query_summary
args:
msg: "debug path"
- tag: cache_main
type: cache
args:
size: 4096
short_circuit: true
cache_negative: true
- tag: forward_main
type: forward
args:
upstreams:
- addr: "udp://1.1.1.1:53"
- tag: seq_main
type: sequence
args:
- exec: "$metrics_main"
- exec: "$recorder_main"
- exec: "$summary_main"
- exec: "$cache_main"
- matches: "!has_resp"
exec: "$forward_main"
- tag: udp_debug
type: udp_server
args:
entry: "seq_main"
listen: ":5353"
适用场景:
- 新策略上线前观察命中路径
- 排查某个域名为什么走了特定分支
- 给 WebUI 或外部系统提供历史查询与实时查询流
排查 client_ip 时要注意:query_recorder 记录的是 OxiDNS 收到 DNS 请求时的传输层来源。如果所有记录都是 127.0.0.1,通常是 systemd-resolved、dnsmasq、AdGuardHome、dae、clash 等本机转发器先接收了客户端请求再转发给 OxiDNS;请检查客户端 DNS 指向、旁路由/NAT 规则和本机代理链路。HTTP/DoH 反向代理部署可在可信边界内配置 src_ip_header 保留真实来源地址。
场景八:DNS 结果驱动网络联动
策略目标:
- 把解析结果同步到系统或设备侧集合
- DNS 决策与后续流量策略联动
- 只对目标域名同步,避免把所有解析结果写入外部系统
plugins:
- tag: target_domains
type: domain_set
args:
exps:
- "domain:stream.example"
- tag: forward_main
type: forward
args:
upstreams:
- addr: "udp://1.1.1.1:53"
- tag: route_sync
type: ros_address_list
args:
address: "172.16.1.1:8728"
username: "api-user"
password: "secret"
async: true
address_list4: "policy_v4"
address_list6: "policy_v6"
- tag: seq_main
type: sequence
args:
- exec: "$forward_main"
- matches: "qname $target_domains"
exec: "$route_sync"
适用场景:
- DNS 驱动的路由或防火墙控制
- 需要把解析结果同步到外部网络系统
- 需要把 DNS 学到的目标地址交给网络设备侧策略使用
组合原则
先决定主路径,再加副作用
推荐顺序如下:
- 先确认主路径。
- 本地应答?
- 缓存?
- 单上游还是多上游?
- 再加补充能力。
- ECS
- TTL 改写
- 双栈偏好
- 最后加观测和联动。
query_summarymetrics_collectoripset/nftset/ros_address_list
能放到 provider 的规则,不要重复写在多个 matcher 里
当规则开始在多个分支中重复出现时:
- 域名规则提取成
domain_set - IP 规则提取成
ip_set
该方式可使策略层聚焦于规则集引用关系,而无需重复维护相同规则文本。