INFO
本頁暫以簡體中文顯示,待繁體中文翻譯完成後更新。
honk 的 dae 配置方言
honk 使用 dae 配置语法的方言。两者对同一段文本的解析结果不同时,以 honk 文档规定的行为为准。本页列出基于源文本的解析器当前采用的规则;dae 一栏只描述其文法(dae_config.g4),不涉及值转换。
词法规则
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
裸值内的 #,如 log_file: /tmp/a#b、use_host: /tmp/a#b 或 group(hk#suffix) | # 是裸字面量内的安全字符 | 紧贴前文的 # 是数据,在旧版截断处产生 legacy-glued-hash 警告。标量路径保留为 /tmp/a#b,子组名称为 hk#suffix。需要注释时,请在 # 前加空白。 | dialect-lexical-01-scalar-hash, dialect-lexical-01-host-hash, dialect-lexical-01-group-hash |
路由规则里紧贴出站名的 #,domain(x) -> proxy#c | 一个裸字面量 proxy#c | 字面目标为 proxy#c,产生 legacy-glued-hash 警告,仍须通过通常的目标校验。注释请写成 -> proxy # comment。 | dialect-lexical-02-outbound-hash |
/* … */ | 块注释,跳过 | 不支持块注释。以 /* 开头的语句产生 unsupported-comment 警告并被忽略,后续物理行仍按配置读取。需要多行注释时,请每行使用 #。 | dialect-lexical-03-block-comment |
声明后的 [key: value],filter: name(x) [add_latency: -500ms] | 作为注解接受 | 不识别;该过滤条件被报告为无法解析并忽略。honk 没有按节点的延迟偏置。 | dialect-lexical-04-annotation |
裸标量内的撇号,如 log_file: /tmp/don't,或已开启的流量参数引号 | 裸值内的撇号是词法错误 | /tmp/don't 是字面值。普通引号只在词法单元开头,或紧接引号外的 (、,、: 时开启(key:'value' 与 key: 'value' 是同一条目);顶层 include 额外识别相邻的带引号路径。流量规则中未在同一物理行闭合的引号产生带位置的 unterminated-quote 错误;请闭合引号,不要依赖花括号恢复结构。 | dialect-lexical-05-apostrophe, dialect-lexical-05-unterminated, dialect-lexical-05-quote-after-colon |
引号或注释内的花括号,如 secret: 'a}b' | 数据 | 引号内和词法单元开头注释内的花括号都是数据。matcher 参数或 User-Agent 后缀内的紧凑 {} 保留为数据;分开的、未加引号的 { 和 } 仍是结构符号。条目尾部紧贴 # 的兼容截断不会隐藏独立的结构花括号。旧版注释花括号解释发生变化时产生 legacy-comment-brace 警告;真正的右花括号须放在注释外。 | dialect-lexical-06-quoted-brace, dialect-lexical-06-comment-brace, dialect-lexical-06-compact-argument, dialect-lexical-06-ua-brace |
块起始符前没有空格,global{ … } | 空白被跳过,仍是块 | 无论位于行内还是行尾,都产生 block-delimiter-spacing 错误。块头与花括号之间须留空白;仍接受 global {} 这样的紧凑空块,group { a {} b {} } 中相邻的声明仍是独立块。 | dialect-lexical-07-glued-opener, dialect-lexical-07-compact-empty, dialect-lexical-07-adjacent-groups |
多余的 },或空文件 | 多余的 } 被拒绝;空输入或只有注释的输入被接受 | 多余的右花括号产生 unmatched-close 警告并被忽略;不含块的 dae 入口文档或独立字符串文档被拒绝。被包含的空文件或纯注释 .dae 片段不贡献配置段。首次 PR2 发布后再评估多余右花括号的兼容行为。 | dialect-lexical-08-extra-closer, dialect-lexical-08-empty, dialect-lexical-08-comment-only |
组名,123 {、香港 {、Hong Kong { | 块名必须是一个 ID | 独立 { 之前的原始块头是动态组名。未知顶层名称产生诊断并被跳过,不会作为插件加载。 | dialect-lexical-09-numeric, dialect-lexical-09-unicode, dialect-lexical-09-spaces |
一行两个声明,global { log_level: debug log_file: x } | 空白分隔的两个声明 | 一个声明:log_level 的值是 debug log_file: x。每行一个 key: value;单行块只容纳一条语句。 | dialect-lexical-10-same-line |
起始花括号另起一行,global 换行 { | 空白(含换行)被跳过 | 普通块的起始花括号不能另起一行。只有顶层 include 保留此兼容语法,允许中间有空行或注释行,并产生带位置的 legacy-include-opener 警告。请把 { 放在 include 块头所在行;首次 PR2 发布后再评估这项兼容行为。 | dialect-lexical-11-split-root, dialect-lexical-11-split-include |
标量与列表
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
带冒号的裸值,bind: 127.0.0.1:53 | 不是一个字面量,必须加引号 | 接受裸写:值是第一个 : 之后的全部文本。 | dialect-scalars-01-bare-colons |
调用形态的值,client_subnet: auto(9.9.9.9) | 函数表达式 | 文本 auto(9.9.9.9) 就是值,由该设置自行解析。 | dialect-scalars-02-call-value |
带引号的列表项,lan_interface: 'eth0', 'eth1' | 两个字面量 | 先拆分列表,再逐项移除一对包围该项的引号,结果为 eth0、eth1。解析结果与旧版不同的引号写法产生 legacy-list-quoting 警告;native_api 的列表没有旧版读法,不产生该警告。检查目标列表仍兼容整体加引号的逗号列表,并产生 legacy-quoted-list 警告;建议逐项加引号或裸写。 | dialect-scalars-03-list, dialect-scalars-03-aggregate |
布尔值 t、y、f、n | 裸字面量 | 宽松设置不区分大小写:true、yes、1、on 为真;false、f、no、n、0、off、t、y 为假。四种单字母简写产生 legacy-bool-shorthand 警告;未知写法为假并报告诊断。建议使用 true 或 false。global.nfqueue_enable 与旧版 experimental.udp_nfqueue.enabled 仍严格解析,拒绝简写。 | dialect-scalars-04-t, dialect-scalars-04-y, dialect-scalars-04-f, dialect-scalars-04-n, dialect-scalars-04-strict |
mark,so_mark_from_dae: 0x10 与 so_mark_from_dae: 10 | 裸字面量 | 两者都按十六进制读取:16 与 16。无法解析的 mark 回退为 0 并报告诊断。 | dialect-scalars-05-0x10, dialect-scalars-05-10, dialect-scalars-05-zz |
毫秒设置里的小数秒,check_tolerance: 1.5s | 裸字面量 | 1500 毫秒。无法解析的毫秒时长(check_tolerance、sniffing_timeout)回退到该设置的默认值并报告诊断;无法解析的秒时长(check_interval、订阅 interval)回退为 0 并报告诊断。 | dialect-scalars-06-1-5s, dialect-scalars-06-never, dialect-scalars-06-seconds |
fixed_domain_ttl 条目 x: 60#note、y: '60'、z: 60 ignored | 60#note 与 '60' 是字面量,60 ignored 是两个词法单元 | 值必须恰好是一个十进制标量。y 存为 60 并产生 legacy-ttl-quoting;x 因 invalid-ttl 被省略,z 因 trailing-value 被省略。请使用 60 或带引号的 60,说明文字放在 # 后。 | dialect-scalars-07-hash, dialect-scalars-07-quoted, dialect-scalars-07-trailing |
未知的 policy,policy: mystery(...) | 任意函数表达式 | 回退为 selector 并报告诊断;参数文本不会被回显。 | dialect-scalars-08-unknown-policy |
node 与 subscription 条目
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
| 分享链接或订阅上的标签 | ID ':' literal;裸字面量不能含 :,所以链接要加引号 | 裸写的开头以第一个 : 之前的文本为标签,除非该冒号是 :// 的开头;加引号的开头只有紧跟在闭引号后的 : 才声明标签,未加引号的 User-Agent 或注释后缀里的冒号只是后缀数据。链接可以裸写;标签与链接都可以加引号。仅在 subscription 里,整体加引号且内含标签的值('paid:https://…')会在去引号后再拆分,无标签的条目以 URL 主机名命名;在 node 里加引号的值就是整个链接('paid:socks5://…' 是未知协议)。 | dialect-entries-01-tagged, dialect-entries-01-bare, dialect-entries-01-quoted-tag, dialect-entries-01-embedded-subtag, dialect-entries-01-embedded-nodetag, dialect-entries-01-tagless |
| 条目行的行尾注释 | # 作为词法单元开头时是注释 | 前面是空格或制表符的 # 结束该行。裸值内紧贴的 # 是数据(…#hk1、?filter='hk'#token、/tmp/a#b)。节点或链接的结束引号后,或订阅的一个完整 (UA) 后缀后,紧贴的 # 以 legacy-glued-hash 警告截断条目尾部,但并非词法注释:其后的独立花括号仍改变块结构。注释的 # 须用空白与前文分隔。其他尾随文本使条目被跳过,并产生 trailing-entry-text 或 legacy-ua-boundary 诊断。 | dialect-entries-02-comment, dialect-entries-02-glued, dialect-entries-02-trailing |
订阅链接后的 'url'(User-Agent) | 不在文法内 | honk 扩展:括号内文本是 User-Agent;未加引号的括号内前有空格的 # 会结束该行,这类 User-Agent 请加引号。 | dialect-entries-03-user-agent, dialect-entries-03-quoted-agent, dialect-entries-03-unquoted-hash |
订阅块:paid: { 之后各占一行的 url: …、ua: …、interval: … 与 } | ID ':' '{' 不是声明 | honk 扩展:订阅的块形式;其设置与其他块一样每行一条。 | dialect-entries-04-block |
带引号的订阅链接后接块:paid: 'url' { 之后各占一行的 ua: …、interval: …、cache: … 或 route: … 与 } | ID ':' literal 已结束声明 | honk 扩展:条目选项;未设置的项取 assets.subscription 与 assets.route。route 取代旧块形式中的 download_detour,同时设置两者时报 conflicting-subscription-route。 | |
node 里冒号前带空格的裸标签,edge : 'socks5://…' | 标签为 edge | 冒号两侧的空白会被规范化:保留节点,标签为 edge,并产生 entry-tag-normalized 信息级诊断。仍接受 edge: … 和带引号的标签。 | dialect-entries-05-spaced-tag |
VLESS 分享链接或扁平序列化 VLESS 节点中的 vless_mode | 旧 VLESS mode 选择器 | 已移除,不作为别名接受。分享链接须使用独立的 udp=、packetEncoding= 与 mux= query。扁平 VLESS 节点会拒绝 vless_mode 的任何存在形式(包括 null),改用 network、packet_encoding 与 multiplex。 | |
扁平序列化非 VLESS 节点上的 vless_mode: legacy | VLESS 之外的旧字段 | 仅作为序列化适配器输出并读取的兼容占位字段,不影响行为。这是唯一的非 VLESS 序列化例外,不是文档支持的 dae 或分享链接语法。 |
路由
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
裸前缀匹配器,!geosite:cn -> proxy、domain:example.com -> proxy | 不是函数调用,拒绝 | 接受为匹配器(geosite、geoip、domain、suffix、keyword、regex、full 前缀)。 | dialect-routing-01-geosite-prefix, dialect-routing-01-domain-prefix |
两个箭头,domain(x) -> proxy->backup | 拒绝 | 出站为字面文本 proxy->backup,产生 legacy-arrow-target 警告。保留此兼容写法,仍须通过通常的目标校验。 | dialect-routing-02-two-arrows |
-> proxy( must ) | 带参数 must 的调用 | 非 direct 目标仍要求精确后缀 (must);proxy( must ) 是名为 proxy( must ) 的出站。direct 会解析选项列表,因此 direct( must ) 是终局规则。 | dialect-routing-03-spaced-must, 直连选项测试 |
括号前有空格,dport (443) -> proxy | 接受 | 返回带位置的 unknown-traffic-predicate 错误。请删除匹配器名称与左括号之间的空格。 | dialect-routing-04-spaced-call |
合取里的未知匹配器,dport(443) && domian(x) -> direct | 文法接受,校验在文法之外 | 返回带位置的 unknown-traffic-predicate 错误,取反条件也不例外。请修正匹配器;不再静默丢弃单个条件。 | dialect-routing-05-unknown, dialect-routing-05-negated |
含多个冒号的参数,dip(2001:db8::/32)、mac(00:11:22:33:44:55) | 不是字面量,需要加引号 | 整体保留:只有识别的 prefix:(geosite:、geoip:、domain:、suffix:、keyword:、regex:、full:)才在其冒号处拆分。 | dialect-routing-06-ipv6, dialect-routing-06-mac |
direct(mark: 10) / direct(mark: 0x10) / direct(mark: 010) | 函数参数;dae 类型解码使用 Go 的 base-0 ParseUint,结果为 10 / 16 / 8 | 只接受十进制或显式 0x/0X 十六进制,结果为 10 / 16 / 10。拒绝二进制/八进制前缀、下划线、正负号、溢出与保留位 0xc0000000。这是有意区别于 dae base-0 解码以及上文 honk 全局 mark 的十六进制优先规则。 | 直连 mark 测试 |
direct(mark: 512, must) / direct(must, mark: 512) 及带 mark 的 fallback: | 选项顺序不限 | 直连规则和 fallback 均接受两种顺序及内部空白。未知/重复直连选项安全报错;只有 direct 支持 mark。合并后最终 fallback 的完整动作(含 mark 与 must)在全部普通规则之后生效。 | 解析测试, include 测试 |
上游 mark 类型与选项行为定义见 routing.ParseOutbound。 运行时低 30 位策略掩码、全局默认值与重启要求见 路由 mark 和套接字 mark。
DNS
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
request 或 response 规则里未加引号的 // | 不是注释 | // 是数据,不是注释。-> asis // note 这类行尾斜杠注释文本使规则无效,产生 legacy-slash-comment 警告并省略整条规则;引号内的斜杠保持字面含义。请将 DNS 行尾 // 注释改为 #。 | dialect-dns-01-slash-comment, dialect-dns-01-quoted-slash |
request 或 response 规则里的 #,qname(a#b) -> reject # note | a#b 是字面量,# note 是注释 | 只有引号外词法单元开头的 # 开始注释,前面可以是空格或制表符。模式保持为 a#b,动作为 reject;与旧版读取结果不同的写法产生 legacy-dns-hash。字面字符 # 可紧贴前文;注释须在引号外用空白分隔。 | dialect-dns-02-hash |
request 或 response 规则里的 -> | 一个箭头 | 规则在第一个引号外的 -> 处拆分;后续箭头留在动作里,并产生 legacy-arrow-target 警告。整个动作转为小写,随后必须与上游声明名称精确匹配:MixedCase 选择 mixedcase,不匹配名为 MixedCase 的声明。此动作与引用名称规则不变。 | dialect-dns-03-two-arrows, dialect-dns-03-mixed-action |
跨行的匹配器调用,qname( 换行 a.example) -> reject | 空白(含换行)被跳过 | DNS 不合并物理行。每条不完整的非空行都被省略,并产生带位置的 incomplete-dns-rule,因此此例产生两条警告。请将 DNS 调用和动作放在同一行。未闭合引号只产生一条词法诊断,不再附加不完整行警告;只有所有块都在引号外闭合时才能恢复解析。 | dialect-dns-04-split-call |
带出站的上游,u: 'udp://1.1.1.1:53' -> proxy 或 u: 'udp://1.1.1.1:53' outbound: proxy | 箭头形式被拒绝(声明不能带 ->);outbound: proxy 形式是相邻的两个声明 | honk 扩展:两种形式都让上游 u 经出站 proxy 拨号;两个后缀都只在 URI 引号外读取。 | dialect-dns-05-arrow-detour, dialect-dns-05-key-detour |
匹配器调用后的文本,dport(443)junk -> proxy、qname(a.example)junk -> reject | 拒绝:箭头必须紧接调用 | 流量路由以带位置的 trailing-matcher-text 错误拒绝配置;DNS 发出警告并省略整条规则。请删除匹配器后的多余文本。 | dialect-dns-06-traffic-junk, dialect-dns-06-dns-junk |
上游行的行尾注释,v: 'udp://8.8.8.8:53' # note | 注释 | 引号外词法单元开头的 # 开始注释,因此地址为 8.8.8.8:53;行为变化产生 legacy-upstream-comment。可以使用普通行尾 # 注释;引号保护地址数据。 | dialect-dns-07-upstream-comment |
带引号的上游 URL 内的 -> 或 outbound: | 数据 | 只有引号外的描述符后缀选择出站;'https://dns.example/q?x=outbound:proxy#frag' 保持为一个 URI。与旧版拆分结果不同的写法产生 legacy-upstream-separator 警告;出站后缀请放在 URL 引号外。 | dialect-dns-08-quoted-outbound, dialect-dns-08-quoted-arrow |
qtype(...) | 函数参数 | 名称 A、AAAA、CNAME、MX、TXT、NS、PTR、SOA、SRV、HTTPS、SVCB、ANY、*(不区分大小写)或十进制 u16;未知名称产生 invalid-qtype 警告并省略整条规则,混合列表和取反条件也不例外。请修正名称或使用数字类型码。显式 qtype() 仍不匹配任何类型;qtype('a,aaaa') 仍选择两种类型,并产生 legacy-quoted-list 警告。建议裸写或逐项加引号。 | dialect-dns-09-names, dialect-dns-09-1-28, dialect-dns-09-typo, dialect-dns-09-aggregate, dialect-dns-09-empty |
组
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
group('hk,jp') | 一个字面量 | 两个子组标签,按 , 与 | 拆分。 | dialect-groups-01-aggregate, dialect-groups-01-pipe |
filter: group() | 无参数的调用 | 显式 group() 不选择任何节点,并产生 empty-subgroup 警告;序列化后再反序列化以及刷新后均保留此行为。需要全部节点时请删除该过滤器。 | dialect-groups-02-empty |
配置段与 include
| 输入 | dae 文法 | honk | 案例 |
|---|---|---|---|
experimental 里的未知内容 | 任意声明 | 未知外层配置项及旧版 udp_nfqueue 中不支持的内容(包括嵌套块)都是错误。clash_api 与 cache_file 中的未知标量键产生 unknown-key 警告并被忽略;这项前向兼容规则不放宽 NFQUEUE 校验。 | dialect-sections-01-outer-key, dialect-sections-01-nfqueue-block, dialect-sections-01-child-key |
global、dns、routing、组设置或已知实验子块中的未知嵌套块 | 任意表达式 | 在块头产生一次 unknown-block 警告,跳过整个已闭合子树,DNS 子块也遵循此规则。子树中的设置和规则不再影响父块;请将已知设置移到文档规定的层级。 | dialect-sections-02-global-wrapper, dialect-sections-02-dns-wrapper, dialect-sections-02-routing-wrapper, dialect-sections-02-group-wrapper |
node 和 subscription 包装块及 subscription 设置中的嵌套包装块 | 没有独立的包装块语法 | 保留有界的兼容遍历,每个包装块产生 legacy-wrapper 警告。group 根层的任意名称都是实际组名,不是包装块。带引号 URL 的订阅块头 tag: 'url' { … } 是带选项的条目,不是包装块:其中形如条目的子项以 unknown-key 忽略。首次 PR2 发布后再评估包装块兼容行为。 | dialect-sections-03-node-wrapper, dialect-sections-03-sub-wrapper |
| 未知根语句和标量键 | 任意标识符 | 结构识别成功后产生警告并忽略;未知根块按完整子树跳过。组名、条目标签、上游名和 TTL 所属域名是动态名称,不是未知配置键。没有箭头的流量语句会被诊断并忽略,但 fallback 声明除外。 | dialect-sections-04-root-statement, dialect-sections-04-unknown-key, dialect-sections-04-unknown-root, dialect-sections-04-traffic-statement |
assets { … } 根配置段 | 不是 dae 配置段 | honk 扩展:geodata、外部 UI 与订阅的下载默认值,见 Assets 配置参考。它取代的五个 experimental 下载配置项仍可读取,每次出现产生一条 legacy-assets-key 警告。 | |
include { … } | 与其他块相同的块 | 只在加载文件时展开模式,顺序与目录限制见配置指南;字符串解析检查结构,但不打开文件。两种模式都会在首次获取词法单元时识别 'first.dae''quoted # name.dae' 这样的相邻带引号路径,保留引号内的 # 和花括号;每个引号必须在同一物理行闭合。只有词法单元开头的 # 引入注释;absolute.dae#note 是字面模式并产生 legacy-include-hash,仍按 .dae 扩展名筛选。 | dialect-sections-05-include, dialect-sections-05-adjacent, dialect-sections-05-hash |
來源:honk 上游文件,採用 GPL-3.0-only 授權條款。
