插件及其参数
写在最前
mosdns 的插件流水线概念
什么是插件: 插件接受并返回一个“请求上下文”。在内部处理请求/应答。
“请求上下文”包含了
客户端来源 IP 等信息。由服务端赋值。不可修改。
客户的请求。插件可以自由修改请求的数据。
应答。初始为空。插件可以自由修改应答的数据
插件流水线: 将多个插件串在一起,就构成了一条流水线。
配置文件中的插件
每个插件都是独立的,互不影响。同类型 type
插件可以初始化任意多个,只要插件的 tag
不重复就行。
一些常用的插件配置已经被 mosdns 预先初始化好了,tag
以 _
开头以便区分。可以直接调用。
mosdns 会按照配置文件中顺序将插件初始化。有些插件需要调用其他插件,比如 sequence,其调用的插件必须在之前配置。否则会因为找不到插件而初始化失败。
可执行插件
_return
预初始化的插件。什么都不做。不会将请求上下文传递给后续流水线。可以用于结束 sequence 流水线。见下文。
流水线逻辑:
正向:跳过后续流水线。
反向:无。
sequence 将多个插件组合成流水线
sequence
可以将多个插件组成一个流水线。sequence
也是插件,所以 sequence
里运行别的sequence
是可以的。
_return
是一个特殊的预初始化插件,可配合 sequence
使用,它只会跳过后续流水线。(注意: “跳过后续流水线”并不是直接将应答返回客户端,而是正向流水线运行结束,开始反向运行。)。
sequence 插件中调用的插件 tag 必须在 sequence 前定义,否则 sequence 找不到对应插件。
初始化参数说明:
cache 缓存
缓存 DNS 应答的插件。
流水线逻辑:
正向:如果请求命中缓存,则将缓存的应答放入“请求上下文”,跳过后续流水线。如果没有命中,则继续执行后续流水线。
反向:缓存应答。
以下预初始化的插件 tag
可直接使用:
_default_cache
: 默认配置的内存缓存。大小 1024。无 lazy cache。
初始化参数说明:
lazy cache,也叫“乐观缓存”,的优缺点:
优点:可大幅提高缓存命中率。流行域名几乎 100% 命中。
缺点:可能影响 DNS 更新频繁的域名正常使用,比如 DDNS,CDN。
仅建议个人使用场景,有相关知识,了解其弊端的专业用户开启。
Metrics 数据:
query_total: 总请求数。
hit_total: 总命中数。(包括 lazy cache 的命中)
lazy_hit_total: lazy cache 总命中数
cache_size: 当前缓存大小。单位: 条。
hosts 域名映射 IP
流水线逻辑:
正向:如果请求的域名在 hosts 内,则将应答放入“请求上下文”,跳过后续流水线。如果不在,则继续执行后续流水线。
反向:无。
初始化参数说明:
虽然都叫 hosts,但本插件所用的格式和平常 Win,Linux 系统内的那个 hosts 文件不一样。
格式:
域名规则在前,IP 在后。支持一行多个 IP,支持 IPv6。
如果域名匹配规则的方式被省略,则默认是
full
完整匹配。域名匹配规则详见 这里。
格式示例:
_prefer_ipv4/6 优先使用 ipv4/6
_prefer_ipv4
和 _prefer_ipv6
是预初始化插件,可直接使用。下面为了表述方便,仅以 _prefer_ipv4
为例。_prefer_ipv6
同理。
_prefer_ipv4
可用让下游客户端支持双栈时优先使用 IPv4。_prefer_ipv4
会自动探测域名是否是双栈,然后只屏蔽双栈域名的 AAAA 请求。相比于强行禁用所有 AAAA 请求的方案,该插件不会影响纯 IPv6 域名的解析。
使用位置要求: 插件的后续序列中必须有转发请求的插件。
流水线逻辑:
正向:同时请求 A 和 AAAA。
反向:根据 A 和 AAAA 的结果,判断域名双栈支持状况,决定屏蔽策略。
sequence 示例:
ecs 为请求附加 ECS
流水线逻辑:
正向:附加 ECS 至请求。
反向:保证请求与应答 ECS 一致。如果源请求中无 ECS (现有 ECS 是插件新附加的),则删除应答中的 ECS 回应。
初始化参数说明:
_no_ecs 删除请求和应答中的 ECS
_no_ecs
是预初始化插件的 tag,可直接使用。
流水线逻辑:
正向:删除请求中的 ECS。
反向:删除应答中的 ECS。
一般放在转发插件前。
ttl 修改应答的生存时间
流水线逻辑:
正向:修改应答的生存时间。
反向:无。
使用位置:一般放在转发插件后。
初始化参数说明:
blackhole 丢弃应答或生成假应答
blackhole
会丢弃应答,或生成特定应答来屏蔽请求。
以下预初始化的插件 tag
可直接使用:
_drop_response
: 丢弃已存在的应答。_new_empty_response
: 生成 Rcode 为 0 的空应答。放入“请求上下文”。(模拟域名存在但没有所请求类型的记录)_new_servfail_response
: 生成 Rcode 为 2 (SERVFAIL: 服务器失败)应答。放入“请求上下文”。_new_nxdomain_response
: 生成 Rcode 为 3 (NXDOMAIN: 域名不存在)应答。放入“请求上下文”。
流水线逻辑:
正向:丢弃或生成对应应答。
反向:无。
初始化参数说明:
ipv4 和 ipv6 的优先级高于 rcode。如果都配置了, A/AAAA 请求会生成 IP 应答,其余类型会生成状态为 RCODE 的应答。
fast_forward 转发请求至上游(自带模块)
mosdns 自带模块。
流水线逻辑:
正向:转发请求至上游,获取应答后放入“请求上下文”。
反向:无。
初始化参数说明:
addr
必需。服务器地址。省略 scheme 默认为 UDP 协议。省略端口号会使用协议的默认值。支持 IP 和域名。格式示例: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
UDPME(v3.5.1+)(实验性):
udpme://8.8.8.8
这是个能过滤掉 UDP 抢答应答的方案。仍然是 UDP 协议。服务器必须支持 EDNS0。如果抢答者不支持 EDNS0,则可以过滤抢答应答。
使用 dig 测试
dig +edns cloudflare.com @服务器地址
观察返回是否有一行EDNS: version: 0
来确定服务器是否支持 EDNS0。绝大多数服务器都支持。
优先使用 IP 地址(如果服务器官方提供)。如果
addr
包含域名,插件需要将其解析成 IP 地址。dial_addr
: 为包含域名的addr
手动指定其 IP 地址。支持端口号。指定后插件连接服务器时无需先解析服务器的域名。能更快建立连接。适用于 IP 万年不变的服务器。bootstrap
: (v4.2+)(实验性) 手动指定用于解析addr
中域名的 bootstrap 服务器。只能是 UDP 服务器。指定后插件每次连接服务器时会先通过该 bootstrap 服务器解析域名。bootstrap 服务器的延时越低越好。HTTP/3 暂不支持该选项。仅支持 Win,Unix 平台。Macos,Plan9 等不支持。系统默认解析: 以上两个参数留空,会使用默认系统解析方式。
优先级:
dial_addr
>bootstrap
> 系统默认。
socks5
: socks5 服务器地址。格式host:port
。数据将会通过该代理中转。暂不支持用户名密码认证。UDP 和启用了 HTTP3 的 DoH 协议暂不支持该设定。trusted
: 是否是可信服务器。可信服务器的任何应答都会被接受。其余服务器只接受 RCODE 为 0 (SUCCESS) 的应答。第一个服务器一定是可信服务器且不可修改。其余默认不可信。idle_timeout
TCP/DoT/DoH 连接复用空连接保持时间。单位: 秒。默认 DoH: 30 ,TCP/DoT: 10。一般不需要改。enable_pipeline
: TCP/DoT 使用 RFC 7766 新的 query pipelining 连接复用模式。启用后可大幅提高连接利用率,减少建立连接/握手的次数,进而降低延时。
并非所有服务器都支持。必须确定服务器支持后再启用该选项。
Tips: 已知 Google 和 Cloudflare 的 TCP/DoT 都是支持的。知名的公共 DNS 服务商大多数都支持该模式。mosdns 自带一个测试命令可以测试服务器是否支持该模式。
enable_http3
: (v3.4.0+)(实验性) DoH 使用 HTTP/3 连接服务器。并非所有服务器都支持。必须确定服务器支持后再启用该选项。Tips: 已知 Google 和 Cloudflare 是支持的。max_conns
: 默认: 2。一般不需要改。大流量场景可适当调大。UDP 协议: 收发数据包使用的套接字数。
启用了 query pipelining 模式的 TCP/DoT 协议: 最大连接数。
DoH 协议: HTTP 的最大连接数。HTTP/3 除外。
insecure_skip_verify
: 禁用 TLS 服务器证书验证。Linux 套接字设定。需要
CAP_NET_ADMIN
权限so_mark
:(v3.7+)。设定 SO_MARK。bind_to_device
: (v4.3+) 设定 SO_BINDTODEVICE。
ca
: 用于 TLS 验证的 CA 证书路径。是数组,可填入多个证书。默认使用系统证书池。
forward 转发请求至上游(dnsproxy)
这个插件使用了 AdguardHome 的请求模块 dnsproxy。
流水线逻辑:
正向:转发请求至上游,获取应答后放入“请求上下文”。
反向:无。
初始化参数说明:
addr
地址格式和 AdguardHome 支持的格式一致。一些示例:
UDP:
8.8.8.8
,208.67.222.222:443
TCP:
tcp://8.8.8.8
DoT:
tls://dns.google
DoH:
https://dns.google/dns-query
DoH3:
h3://dns.google/dns-query
DoQ:
quic://dns.adguard.com
DNS stamp:
sdns://...
详见 dnscrypt.info
上述列表和参数说明不一定是最新的,请以 dnsproxy 的 README 为准。
ipset 将应答 IP 写入到系统 ipset
流水线逻辑:
正向:将应答 IP 写入 ipset。
反向:无。
初始化参数说明:
插件添加新 IP 时相当于执行了
ipset add <set_name> <IP>/<mask>
命令。插件使用 netlink 直接与内核通信,不依靠
/sbin/ipset
命令。该插件不会创建 set。set 需要由用户提前创建。必须为
hash:net
类型。建议设置非零的timeout
属性。实现自动清除长时间没有用到的地址。
创建 ipset 表命令示例:
nftset 将应答 IP 写入到系统 nftables
流水线逻辑:
正向:将应答 IP 写入 nftables。
反向:无。
初始化参数说明:
插件添加新 IP 时相当于执行了
nft add element <table_family> <table_name> <set_name> {<IP>/<mask>...}
命令。插件使用 netlink 直接与内核通信,并不依靠
/sbin/nft
命令。该插件不会创建对应的 set。set 需要由用户提前创建。
set 建议设置
timeout
来实现自动清除长时间没有用到的地址。set 建议设置
interval
flag。插件会自动识别这个 flag,然后会以 IP 段的方式存储 IP。
创建 nftables set 命令示例:
bufsize 限制请求的 EDNS0 的 UDP 负载大小
旧插件。建议使用新的 _misc_optm 插件。
流水线逻辑:
正向:修改请求的 EDNS0 UDPSIZE (如果请求有 EDNS0)。
反向:无。
初始化参数说明:
padding 填充 DNS 报文至固定长度 (实验性)
参考 RFC 8467,使用 EDNS0 的 Padding Option 将 DNS 报文用 0 填充至固定长度。据 Google 说 (Google Plublic DNS 文档) 能防止流量分析保护隐私。包含 3 个预定义插件。
_pad_query
: 填充请求
流水线逻辑:
正向:将请求填充至 128 bytes。
反向:无。
使用位置要求: 该插件到转发插件之间不能有修改请求的插件。否则请求大小可能会变,影响效果。
_enable_conditional_response_padding
和 _enable_response_padding
: 填充应答:
流水线逻辑:
正向:无。
反向:填充应答至 468 bytes。
_enable_response_padding
是如果客户端请求包含 EDNS0,就会填充应答。而_enable_conditional_response_padding
则是如果客户端对请求进行了填充,才会填充应答。
使用位置要求: 反向流水线填充应答后,直至流水线结束,不能有修改应答的插件。否则应答大小可能会变,影响效果。
redirect 替换请求的域名 (实验性)
替换(重定向)请求的域名。请求域名 A,但返回域名 B 的记录。
流水线逻辑:
正向:替换请求的 QUESTION NAME。比如将请求域名 A 替换为 B。
反向:修改应答的 ANSWER 的 NAME,比如将 B 替换回 A。使之看起来像请求 A 的记录。
注意: 没有能完美替换请求域名的方法。本插件的替换方式对于常见的 A,AAAA,TXT 等仅依赖 QUESTION 和 ANSWER 的请求是有效的。但不保证兼容其他类型请求以及各种 EDNS0 扩展。
初始化参数说明:
域名匹配规则
: 如果匹配方式被省略,则默认是full
完整匹配。域名匹配方式详见 域名匹配规则。
arbitrary 返回任意记录 (实验性) (v4.0+)
arbitrary 可以载入任意记录,并在匹配到对应请求时生成包含这些记录的应答,
流水线逻辑:
正向:如果找到对应记录,则生成应答,终止跳过后续流水线。如果不在,则继续执行后续流水线。
反向:无。
初始化参数说明:
不同记录的文本格式请自行搜索。关键词: <记录类型> dns record wikipedia
。在英文 wikipedia 可以直接找到绝大多数记录的格式。
暂不支持从外部数据载入记录。
_misc_optm 转发服务器优化大杂烩 (实验性) (v4.0+)
预定义插件,可直接使用。
适用于转发服务器。
流水线逻辑:
正向:
屏蔽掉互联网公共上游不能处理的请求(多个 QUESTION 和非 IN CLASS)。(立刻返回 REFUSE,跳过后续流水线。)
将 EDNS0 UDPSIZE 限定在 1200。(v4.5+)
反向
去除 A/AAAA 应答的 CNAME 记录。减小应答长度。
去除应答的 Padding。减小应答长度。
随机打乱 A/AAAA 应答的 IP。负载均衡。
如果请求无 EDNS0,去除上游应答的 EDNS0。保持 EDNS0 状态一致。
建议流水线位置: 流水线起始。
reverse_lookup IP 反查域名 API (v4.2+)(实验性)
该插件会缓存应答中的 IP 与 域名的关系。可在本地实现无延时的"有效 IP -> 域名"查询。支持 PTR 和 HTTP API。
流水线逻辑:
正向:如果是 PTR 请求,并且命中缓存,则生成应答,跳过后续流水线。如果没有命中缓存,则继续执行后续流水线。
反向:将 A/AAAA 应答的 IP 写入缓存。
初始化参数说明:
建议流水线位置: 流水线起始。务必放在 cache
前,防止 cache
命中缓存后不执行 reverse_lookup
导致无法记录 IP。
查找缓存中 IP 对应域名的 API:http://<api_addr>/plugins/<plugin_tag>?ip=<ip_addr>
返回: 如果缓存中找到对应域名,则返回域名。如果缓存中没有找到对应域名,则返回空。如果参数不对则返回 HTTP 400。
示例: http://127.0.0.1:8080/plugins/my_reverse_lookup?ip=8.8.8.8
,返回 dns.google.
注意返回的是 fully qualified 域名,末尾有 .
。
metrics_collector 统计数据收集器 (v4.2+)(实验性)
收集 prometheus metrics 数据。
流水线逻辑:
正向:query_total =+1,thread =+1,response_latency_millisecond 开始计时。
反向:err_total =+1 (如果出错),thread =-1,response_latency_millisecond 结束计时。
请求经过插件时,插件会收集
query_total 经过该插件的总请求数。
err_total 插件所在 sequence 的后续插件的总出错数。
thread 当前经过该插件的线程数。
response_latency_millisecond 插件所在 sequence 的后续插件的应答延时。
数据项名称为 mosdns_plugin_<plugin_tag>_<name>
。
建议流水线位置: 放在流水线起始位置就可以统计本条流水线的数据。
client_limiter 限制客户端的 QPS (v4.2+)(实验性)
限制客户端(以 IP 或 IP 段区分)的最大每秒请求数 QPS。
流水线逻辑:
正向:如果客户端 QPS 超过阈值,则生成 REFUSE 应答,跳过后续流水线。
反向:无。
建议流水线位置: 流水线起始。
注意: 该插件只能用于向非恶意客户端“友好”地回复 REFUSED。不能防攻击。
edns0_filter 过滤请求的 EDNS0 OPTION (实验性)(v4.4.1+)
过滤/限制客户端可以使用 EDNS0 OPTION。
TIps: 如果后面配置有启用了 cache_everything 的 cache 插件,该插件可用于提高缓存利用率。比如移除 Cookie 和 Padding,或只允许 ECS。
流水线逻辑:
正向:从请求中移除/保留指定的 EDNS0 OPTION。
反向:无。
以下预初始化的插件 tag
可直接使用:
_edns0_filter_no_edns0
: 删除应答的 EDNS0。_edns0_filter_ecs_only
: 只保留 ECS。
初始化参数说明:
建议流水线位置: 流水线起始,cache 前,转发插件前。
_query_summary (v4.5.3+) 记录请求摘要
在 info 级别记录请求。包括请求的域名,类型,客户端地址,应答状态,请求处理时间等。
建议流水线位置: 流水线起始,cache 前。
注: 如果请求没有或有多个 QUESTION,则不会有记录。
sleep 延时执行
调试。模拟延时用。
流水线逻辑:
正向:延时。
反向:无。
初始化参数说明:
匹配器插件
匹配器插件匹配请求和应答状态,返回 true
or false
。
query_matcher 匹配请求的特征
以下预初始化的插件 tag
可直接使用:
_qtype_AAAA
: 请求的 QTYPE 是 AAAA。_qtype_A_AAAA
: 请求的 QTYPE 是 A 或 AAAA。_query_edns0
: 请求包含 EDNS0。
初始化参数说明:
如果一个匹配器内设定了多个条件,则必须满足全部条件这个匹配器才会为 true
。
response_matcher 匹配应答的特征
以下预初始化的插件 tag
可直接使用:
_response_valid_answer
: 应答包含有效的 ANSWER 记录(ANSWER 中有记录能与 QUESTION 对应)。(v4.0.0+)
初始化参数说明:
如果一个匹配器内设定了多个条件,则必须满足全部条件这个匹配器才会为 true
。
域名匹配器
配置示例:
文本域名数据一条规则一行。如果域名匹配方式被省略,则默认是 domain
域匹配。
域名匹配规则说明详见: 这里
IP 匹配器
配置示例:
关于 v2ray 数据包
mosdns 支持从 v2ray 数据包 (俗称 dat 文件)载入数据,但受限于 v2ray 数据包的打包格式,mosdns 从中读取数据,无论读取多少,都要完整解包。多个插件读取多次会出现重复解包的情况。性能不好的设备(主要是嵌入式路由等)上可能造成 mosdns 启动时间显著变长(数秒)。其他设备影响不大。
优化 v2ray 数据包加载速度:
(推荐)自己提前解包:
mosdns v2dat
小工具命令可以解包数据文件成独立的文本文件。尽可能使用多标签
geoip.dat:cn,us... 一次载入全部所需数据,而非多行。写成多行会造成重复解包。
补充
域名匹配规则
域名规则有多个匹配方式:
以
domain:
开头,域匹配。e.g:domain:google.com
会匹配自身google.com
,以及其子域名www.google.com
,maps.l.google.com
等。以
full:
开头,完整匹配。e.g:full:google.com
只会匹配自身。以
keyword:
开头,关键字匹配。e.g:keyword:google.com
会匹配包含这个字段的域名,如google.com.hk
,www.google.com.hk
。以
regexp:
开头,正则匹配(Golang 标准)。e.g:regexp:.+\.google\.com$
。
如果没有指定匹配方式,不同插件有不同的缺省值。
匹配方式按如下顺序生效: full
> domain
> regexp
> keyword
。
相同匹配方式的规则按如下顺序生效:
domain
规则: 子域名优先。比如如果同时存在规则google.com
和com
。www.google.com
会优先匹配google.com
,然后com
。(v3.9.0+)regexp
和keyword
规则生效顺序为规则导入的顺序。
性能:
domain
和full
匹配使用 HashMap,复杂度 O(1)。每 1w 域名约占用 1M 内存。keyword
和regexp
匹配需遍历,复杂度 O(n)。
到底了!没有找到想要的功能么?提交一个 Feature request。
Last updated