Sequence 插件
sequence 是一个 可执行插件 ,可以被其他插件调用。因其功能较多,单独写在本页面。
写在最前
参数帮助说明
{ arg1 | arg2 | ... }
代表这几个参数必需选择其中一个(多选一)。[ arg ]
代表该参数是可选的。可省略。...
表示之前的参数可以无限重复。*n
表示之前的参数可以重复 n 次 。没有符号的
arg
表示该参数不可省略。
参数
初始化参数说明:
sequence 插件引用的所有已定义的插件 tag 必须在 sequence 前定义,否则 sequence 找不到对应插件。
一个 sequence 由多个 rule 构成。一个 rule 由零个或多个条件和一个操作构成。sequence 会依次执行每个 rule 。
可以把 sequence 近似成处理 DNS 请求的 iptables / nftables 的 chain 。复杂的处理逻辑可以配置多个 sequence 然后配合 accept/reject/jump/goto/return
操作在 sequence 之间跳跃。
可执行插件列表见:
可执行插件错误处理:
如果遇到插件抛出错误,sequence 不会继续执行后续规则,并继续抛出该错误。
内建匹配器
resp_ip
匹配应答 A 和 AAAA 记录的 IP 。如果应答有多个 IP 只要任意 IP 匹配即为 true 。
参数:
示例:
ip
可以是 IPv4/6, CIDR 。ip_set_tag
是类型为 ip_set 插件的 tag 。ip_list_file
是文本类型的 IP/CIDR 表。
client_ip
匹配客户端的 IP 。
参数和示例和上文的 resp_ip 相同。
ptr_ip
匹配 PTR 请求的 IP。
参数和示例和上文的 resp_ip 相同。
qname
匹配请求的 QNAME 。
参数: qname { domain_rule | $domain_set_tag | &domain_list_file } ...
示例: qname google.com full:google.com $local_domains &./local_domains.txt
domain_rule
是域名表达式。支持扩展。详见 域名匹配规则。domain_set_tag
是类型为 domain_set 插件的 tag 。domain_list_file
是文本类型的域名表达式表 。
cname
匹配应答的 CNAME 记录。如果应答有多个 CNAME 只要任意 CNAME 匹配即为 true 。
参数和示例和上文的 qname 相同。
qclass
匹配请求的 QCLASS。
参数: qclass [uint16] ...
示例: qclass 1 2 3
qtype
匹配请求的 QTYPE。
参数和示例和上文的 qclass 相同。
rcode
匹配应答的 RCODE。
参数和示例和上文的 qclass 相同。
has_resp
如果有应答,返回 true 。
has_wanted_ans
如果有期望的 ANSWER,返回 true 。"期望的ANSWER "指应答的 ANSWER 中包含和 QUESTOIN 类型相同的 record。比如请求 A 记录,应答里返回了 A 记录,则该判断为 true。请求 AAAA 记录,虽然返回了SUCCESS 应答但无 AAAA 记录,返回 false 。
mark
参数: mark [uint32] ...
示例: mark 1 2 3
请求存在任意指定的标记即为 true 。
string_exp
(实验性) 字符串匹配器。
参数: string_exp string_src op [arg_string]
示例: string_exp
server_nameeq a.b.c d.e.f
string_src
: 匹配的字符串来源。可以是
url_path: 来自 DoH 服务端请求的 url path 。
server_name: 来自服务端 TLS (DoH,DoT,DoQ) 的 SNI。
$env: 以 $ 开头,环境变量的值。
op
是匹配方式。可以是 eq
相等,prefix
包含前缀,suffix
包含后缀,contains
包含,regexp
正则,zl
字符串长度为零。
arg_string
是匹配参数,目前除了 zl 无参数,其余匹配方式均可包含多个字符串作为匹配规则。任意规则匹配即返回 true 。
注意: 受格式限制,目前不支持带空格的规则参数。
其他匹配器
_true 和 _false
永远返回 true 和 false 。方便脚本生成占位符。
_
前缀没有别的意义,只是防止匹配器名在某些配置格式里被误识别成 bool 类型。
env
参数: env env_key [env_value]
示例: env CACHE_ENABLED
, env NETWORK_TYPE lan
。
启动时查找 env_key
,如果值和 env_value
一致则返回 true。如果 env_value
省略,则 env_key
存在(包括零值的情况)即返回 true 。
random
参数: random prob_float64
示例: random 0.5
以 prob_float64
的概率返回 true 。
内建操作
forward
转发请求至上游服务器获取应答。
参数: forward upstream [upstream]...
示例: forward 8.8.8.8 tls://8.8.8.8
可配置多个上游。会并发请求,取最先返回的应答。如果超过 3 个上游,会随机选取 3 个上游并发。
upstream
支持四种协议。格式示例:
UDP:
8.8.8.8
,208.67.222.222:443
TCP:
tcp://8.8.8.8
DoT:
tls://8.8.8.8:853
,tls://dns.google
DoH (RFC8484 GET):
https://8.8.8.8/dns-query
,https://dns.google/dns-query
Tips: 使用 IP 地址能更快建立连接,因为不用解析服务器的 IP。除非情况特殊,否则不要使用带域名的地址。
这是个便捷设置。如需更多高级功能 (HTTP3,Socks5,SO_MARK...),可配置独立的 forward 插件。
cache
DNS 缓存。如果请求命中缓存,则将缓存的应答放入请求。
当某一请求经过 cache 后,cache 会在这个请求处理流程结束时自动将应答放入缓存。用户无需介入。
不支持扩展 DNS 协议 (即 EDNS0)。
参数: cache [size]
,size
是缓存大小,单位: 条,默认 1024。
示例: cache 1024
这是个便捷设置。如需更多高级功能 (lazy cache,缓存存盘...),可配置独立的 cache 插件。
black_hole
生成包含特定 IP 的应答。
参数: black_hole [ip] ...
示例: black_hole 127.0.0.1 ::1 0.0.0.0
会自动识别参数中的 IPv4/6 。如果参数中指定了多个 IPv4/6,会全部包含在应答内。如果某一 IP 类型未指定,则不会生成对应类型的应答。
drop_resp
丢弃应答。用于触发 fallback。
ecs
附加 ECS (EDNS0 Client Subnet) 至请求。支持 IPv4/6。IPv4 会使用 /24 mask,IPv6 使用 /48 。
参数 (v5.3+): ecs [ip]
参数 (v5.2 以前)(弃用): ecs [ip/mask] [ip/mask]
。v5.3+ 后只会用第一个 IP,mask 会忽略。
示例: ecs 1.2.3.4
forward_edns0opt
(实验性)(v5.3+) 允许客户端的这些 EDNS0 Option 转发至上游。
参数: forward_edns0opt [option_code] ...
注意:
此插件不可以执行多次! 否则转发至上游的请求中 EDNS0 Option 将出现重复,导致协议错误。
并不是所有 EDNS0 Option 都能被转发。此插件设计的目是转发 10 (Cookie) 和 15 (Extended DNS Error)。
ipset
(实验性) 写入应答 IP 至 ipset 。仅支持 Linux 。插件会直接用 netlink 和内核通信,不依赖也不运行 ipset 命令,效率很高。
参数: ipset [set_name,set_family,mask]*2
示例: ipset my_set,inet,24 my_set6,inet6,48
set_family
={ inet | inet6 }
mask
是写入 IP 时使用的掩码
nftset
(实验性) 写入应答 IP 至 nftables 。仅支持 Linux 。插件会直接用 netlink 和内核通信,不依赖也不运行 nft 命令,效率很高。
参数:
示例:
table_family
={ ip | ip6 | inet }
table 表的类型。set_dtype
={ ipv4_addr | ipv6_addr }
set 的类型。mask
是写入 IP 时使用的掩码。插件会自动判断 set 是否带有 interval 这个 flag,如果 set 有 interval flag 的话,会以 IP 段的形式写入 set 。
query_summary
以 info 级别在 log 打印请求的摘要。包含: 请求的域名,类型,客户端 IP,应答的 RCODE,错误信息,后续规则处理请求的用时。
参数: query_summary [ msg_title ]
示例: query_summary query from server 1
msg_title
的文字会写在 log 的msg
键上。
如果一个请求经过了多个 query_summary,log 打印的顺序是反的,即先打印最后经过的 query_summary 的 log。这不是 bug 。
metrics_collector
(实验性) 收集 prometheus metrics 数据。
参数: metrics_collector collector_name
collector_name
不可重复。
暴露的 metrics 数据项名称为
mosdns_metrics_collector_<metric_name>{name=collector_name}
。
插件会收集以下 metric:
query_total 经过该收集器的总请求数。
err_total 该收集器的后续规则的总出错数。
thread 该收集器后续规则的线程数。(此时有多少请求正在被后续规则处理中)
response_latency_millisecond 该收集器后续命令返回的延时。
prefer_ipv4/6
希望客户端解析双栈域名 IP 时,只返回 IPv4/6 。但不影响纯 IPv6/4 (单栈)域名的解析。
prefer_ipv4
和 prefer_ipv6
是两个操作。下面为了表述方便,仅以 prefer_ipv4
为例。prefer_ipv6
同理。
prefer_ipv4
让下游客户端支持双栈时优先使用 IPv4。prefer_ipv4
处理 AAAA 请求时会自动发送 A 请求测试域名是否是双栈,该新产生的 A 请求会和原 AAAA 请求一并继续执行后续规则。如果最后 A 和 AAAA 请求都获得到了 IP (域名为双栈),则原 AAAA 请求被屏蔽。这样客户端只能收到 A 记录,进而强迫客户端使用 IPv4
(实验性特性)(v5.3+) 插件会缓存域名的双栈支持情况,以避免频繁测试。缓存大小 65535 。缓存时长 1 小时。暂不支持自定义。
使用位置要求: 后续规则必须能生成应答 (比如有 forward)。
sequence 示例:
ttl
修改应答的 TTL。
参数: ttl { fix | min-max }
示例: ttl 300
将 ttl 固定在 300, ttl 300-600
限制 ttl 在 300 到 600 之间。ttl 300-0
限制 ttl 不小于 300 。
mark
在请求上打标记。
参数: mark [uint32] ...
示例: mark 1 2 3
调试用
sleep
等待一段时间。增加/模拟延时用。
参数: sleep millisecond
debug_print
以 info 级别在 log 打印完整的请求和应答信息。
参数: debug_print [msg_title]
示例: debug_print query from server 1
msg_title
的文字会写在 log 的msg
键上
内建跳转操作
accept
停止后续规则执行。如果本 sequence 存在上级 sequence,所有上级的 sequence 也不再继续执行后续规则。
reject
参数: reject [rcode]
示例: reject 5
和 accept 一样,如果本 sequence 存在上级 sequence,所有上级的 sequence 也不再继续执行后续规则。同时生成 rcode
应答。不指定 rcode
默认为 5 (REFUSED) 。
return
停止后续规则执行。如果所在 sequence 是从另一 sequence jump 过来的,则返回源 sequence 继续执行。
goto
参数: goto sequence_tag
示例: goto my_next_sequence
sequence_tag
是目标 sequence 插件的 tag。将不再执行本 sequence 后续规则,开始执行目标 sequence 。
jump
参数: jump sequence_tag
示例: jump my_next_sequence
sequence_tag
是目标 sequence 插件的 tag。将开始执行目标 sequence,目标 sequence 结束或 return 后,返回本 sequence 继续执行。目标 sequence accept/reject 后,本 sequence 和所有上级的 sequence 不再继续执行后续规则。
mark 高级用法示例
实现逻辑或,单次匹配后执行多个 exec,以及实现 if ... else。
Last updated