跳转到正文

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 ignored60#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: legacyVLESS 之外的旧字段仅作为序列化适配器输出并读取的兼容占位字段,不影响行为。这是唯一的非 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 # notea#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 许可证。