Comment on page
Sequence 插件
{ arg1 | arg2 | ... }
代表这几个参数必需选择其中一个(多选一)。[ arg ]
代表该参数是可选的。可省略。...
表示之前的参数可以无限重复。*n
表示之前的参数可以重复 n 次 。- 没有符号的
arg
表示该参数不可省略。
初始化参数说明:
tag: ""
type: "sequence"
args: # []rule
- matches: # []string, 匹配条件。多个匹配条件为 AND 关系。
- qname $ad_domain # [!]{ 内置匹配名称 | $已定义的匹配器插件tag } [参数]
- "!qname $ad_domain" # !前缀代表取反。
exec: reject 3 # string, { 内置操作名称 | $已定义的可执行插件tag } [参数]
- exec: $forward_google # matches 条件可省略。
sequence 插件引用的所有已定义的插件 tag 必须在 sequence 前定义,否则 sequence 找不到对应插件。
一个 sequence 由多个 rule 构成。一个 rule 由零个或多个条件和一个操作构成。sequence 会依次执行每个 rule 。
可以把 sequence 近似成处理 DNS 请求的 iptables / nftables 的 chain 。复杂的处理逻辑可以配置多个 sequence 然后配合
accept/reject/jump/goto/return
操作在 sequence 之间跳跃。可执行插件列表见:
错误处理:
如果遇到插件抛出错误,sequence 不会继续执行后续规则,并继续抛出该错误 。
配置示例:
1
tag: ""
2
type: "sequence"
3
args:
4
# 屏蔽某些域名,比如广告域名。
5
- matches:
6
- qname $ad_domain
7
exec: reject 3
8
- ...
9
10
# 将内网请求转交给 handle_local_query sequence 另行处理。
11
- matches:
12
- qname local internal.my.domain
13
exec: goto handle_local_query
14
- matches:
15
- ptr_ip 10.0.0.0/8
16
exec: goto handle_local_query
17
18
# 让某些域名跳过 cache,比如的 DDNS 域名。然后仅
19
# 修改 DDNS 域名的 TTL。
20
- matches:
21
- "!qname my.ddns.domain"
22
exec: cache 1024
23
- exec: forward 8.8.8.8
24
- matches:
25
- qname my.ddns.domain
26
exec: ttl 1
27
28
# env 实现"开关功能"。
29
# 运行 mosdns 时设定 MOSDNS_ENABLE_CACHE 环境变量即可开启 cache 功能。
30
- matches:
31
- env MOSDNS_ENABLE_CACHE
32
exec: cache 1024
33
- ...
匹配应答 A 和 AAAA 记录的 IP 。如果应答有多个 IP 只要任意 IP 匹配即为 true 。
参数:
resp_ip { ip | $ip_set_tag | &ip_list_file } ...
示例:
resp_ip 192.168.1.1/24 8.8.8.8 $local_ips &./local_ips.txt
ip
可以是 IPv4/6, CIDR 。ip_list_file
是文本类型的 IP/CIDR 表。
匹配客户端的 IP 。
匹配 PTR 请求的 IP。
匹配请求的 QNAME 。
参数:
qname { domain_rule | $domain_set_tag | &domain_list_file } ...
示例:
qname google.com full:google.com $local_domains &./local_domains.txt
domain_list_file
是文本类型的域名表达式表 。
匹配应答的 CNAME 记录。如果应答有多个 CNAME 只要任意 CNAME 匹配即为 true 。
匹配请求的 QCLASS。
参数:
qclass [uint16] ...
示例:
qclass 1 2 3
匹配请求的 QTYPE。
匹配应答的 RCODE。
如果有应答,返回 true 。
如果有期望的 ANSWER,返回 true 。"期望的ANSWER "指应答的 ANSWER 中包含和 QUESTOIN 类型相同的 record。比如请求 A 记录,应答里返回了 A 记录,则该判断为 true。请求 AAAA 记录,虽然返回了SUCCESS 应答但无 AAAA 记录,返回 false 。
参数:
mark [uint32] ...
示例:
mark 1 2 3
请求存在任意指定的标记即为 true 。
(实验性) 字符串匹配器。
参数:
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 。方便脚本生成占位符。
_
前缀没有别的意义,只是防止匹配器名在某些配置格式里被误识别成 bool 类型。参数:
env env_key [env_value]
示例:
env CACHE_ENABLED
, env NETWORK_TYPE lan
。启动时查找
env_key
,如果值和 env_value
一致则返回 true。如果 env_value
省略,则 env_key
存在(包括零值的情况)即返回 true 。参数:
random prob_float64
示例:
random 0.5
以
prob_float64
的概率返回 true 。转发请求至上游服务器获取应答。
参数:
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。除非情况特殊,否则不要使用带域名的地址。
DNS 缓存。如果请求命中缓存,则将缓存的应答放入请求。
当某一请求经过 cache 后,cache 会在这个请求处理流程结束时自动将应答放入缓存。用户无需介入。
不支持扩展 DNS 协议 (即 EDNS0)。
参数:
cache [size]
,size
是缓存大小,单位: 条,默认 1024。示例:
cache 1024
生成包含特定 IP 的应答。
参数:
black_hole [ip] ...
示例:
black_hole 127.0.0.1 ::1 0.0.0.0
会自动识别参数中的 IPv4/6 。如果参数中指定了多个 IPv4/6,会全部包含在应答内。如果某一 IP 类型未指定,则不会生成对应类型的应答。
丢弃应答。用于触发 fallback。
附加 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
(实验性)(v5.3+) 允许客户端的这些 EDNS0 Option 转发至上游。
参数:
forward_edns0opt [option_code] ...
注意:
- 此插件不可以执行多次! 否则转发至上游的请求中 EDNS0 Option 将出现重复,导致协议错误。
- 并不是所有 EDNS0 Option 都能被转发。此插件设计的目是转发 10 (Cookie) 和 15 (Extended DNS Error)。
(实验性) 写入应答 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 时使用的掩码
(实验性) 写入应答 IP 至 nftables 。仅支持 Linux 。插件会直接用 netlink 和内核通信,不依赖也不运行 nft 命令,效率很高。
参数:
nftset [table_family,table_name,set_name,set_dtype,mask]*2
示例:
nftset inet,my_table,my_set,ipv4_addr,24 inet,my_table,my_set,ipv6_addr,48
table_family
={ ip | ip6 | inet }
table 表的类型。set_dtype
={ ipv4_addr | ipv6_addr }
set 的类型。mask
是写入 IP 时使用的掩码。插件会自动判断 set 是否带有 interval 这个 flag,如果 set 有 interval flag 的话,会以 IP 段的形式写入 set 。
以 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 。
(实验性) 收集 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 该收集器后续命令返回的延时。
希望客户端解析双栈域名 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 示例:
# 所有请求都优先返回 ipv4,屏蔽 ipv6。
- exec: prefer_ipv4
- ...
- exec: forward 8.8.8.8
# 配合匹配器实现仅特定域名生效。
- matches:
- qname my.domain
exec:
- prefer_ipv4
- ...
- exec: forward 8.8.8.8
修改应答的 TTL。
参数:
ttl { fix | min-max }
示例:
ttl 300
将 ttl 固定在 300, ttl 300-600
限制 ttl 在 300 到 600 之间。ttl 300-0
限制 ttl 不小于 300 。在请求上打标记。
参数:
mark [uint32] ...
示例:
mark 1 2 3
等待一段时间。增加/模拟延时用。
参数:
sleep millisecond
以 info 级别在 log 打印完整的请求和应答信息。
参数:
debug_print [msg_title]
示例:
debug_print query from server 1
msg_title
的文字会写在 log 的msg
键上
停止后续规则执行。如果本 sequence 存在上级 sequence,所有上级的 sequence 也不再继续执行后续规则。
参数:
reject [rcode]
示例:
reject 5
和 accept 一样,如果本 sequence 存在上级 sequence,所有上级的 sequence 也不再继续执行后续规则。同时生成
rcode
应答。不指定 rcode
默认为 5 (REFUSED) 。停止后续规则执行。如果所在 sequence 是从另一 sequence jump 过来的,则返回源 sequence 继续执行。
参数:
goto sequence_tag
示例:
goto my_next_sequence
sequence_tag
是目标 sequence 插件的 tag。将不再执行本 sequence 后续规则,开始执行目标 sequence 。参数:
jump sequence_tag
示例:
jump my_next_sequence
sequence_tag
是目标 sequence 插件的 tag。将开始执行目标 sequence,目标 sequence 结束或 return 后,返回本 sequence 继续执行。目标 sequence accept/reject 后,本 sequence 和所有上级的 sequence 不再继续执行后续规则。实现逻辑或,单次匹配后执行多个 exec,以及实现 if ... else。
- tag: main
type: sequence
args:
# 匹配成功后打标
# 打相同标签可实现"逻辑或"
- matches:
- "match_A"
exec: mark 123456789
- matches:
- "match_B"
exec: mark 123456789
# 连续执行
- matches: mark 123456789
exec: do_something_1
- matches: mark 123456789
exec: do_something_2
# ...
# 连续执行 else
- matches: "!mark 123456789"
exec: else_do_something_1
- matches: "!mark 123456789"
exec: else_do_something_2
Last modified 1mo ago