From b300eed5e82a16bc70812bc986739e08ff151931 Mon Sep 17 00:00:00 2001 From: Fangliding Date: Wed, 17 Jun 2026 20:11:51 +0800 Subject: [PATCH] Refactor finalmask --- docs/config/transports/finalmask.md | 250 +++++++++++++++---------- docs/en/config/transports/finalmask.md | 250 +++++++++++++++---------- docs/ru/config/transports/finalmask.md | 250 +++++++++++++++---------- 3 files changed, 465 insertions(+), 285 deletions(-) diff --git a/docs/config/transports/finalmask.md b/docs/config/transports/finalmask.md index 233b796a..668b9755 100644 --- a/docs/config/transports/finalmask.md +++ b/docs/config/transports/finalmask.md @@ -73,51 +73,57 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 } ``` -> `type`: header-custom | fragment | sudoku +> `type`: string 该层伪装的类型。 -> `settings`: header-custom | fragment | sudoku +> `settings`: string -该伪装类型的具体设置(每个类型的字段见下) +该伪装类型的具体设置。 + +每个类型的字段见下 ### header-custom ```json { - "clients": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } + "type": "header-custom", + // [!code focus:35] + "settings": { + "clients": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "servers": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "errors": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] ] - ], - "servers": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ], - "errors": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ] + } } ``` @@ -135,10 +141,14 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 ```json { - "packets": "tlshello", - "length": "100-200", - "delay": "10-20", - "maxSplit": "3-6" + "type": "fragment", + // [!code focus:6] + "settings": { + "packets": "tlshello", + "length": "100-200", + "delay": "10-20", + "maxSplit": "3-6" + } } ``` @@ -160,14 +170,18 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 ```json { - "password": "", - "ascii": "", + "type": "sudoku", + // [!code focus:10] + "settings": { + "password": "", + "ascii": "", - "customTable": "", // 官方文档字段名为 custom_table - "customTables": [""], // 官方文档字段名为 custom_tables + "customTable": "", // 官方文档字段名为 custom_table + "customTables": [""], // 官方文档字段名为 custom_tables - "paddingMin": 0, // 官方文档字段名为 padding_min - "paddingMax": 0 // 官方文档字段名为 padding_max + "paddingMin": 0, // 官方文档字段名为 padding_min + "paddingMax": 0 // 官方文档字段名为 padding_max + } } ``` @@ -191,13 +205,15 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 } ``` -> `type`: header-custom | header-dns | header-dtls | header-srtp | header-utp | header-wechat | header-wireguard | mkcp-original | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp +> `type`: string 该层伪装的类型。 -> `settings`: header-custom | header-dns | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp +> `settings`: string -该伪装类型的具体设置(每个类型的字段见下) +该伪装类型的具体设置。 + +每个类型的字段见下 ### header-custom @@ -205,22 +221,26 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 ```json { - "client": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ], - "server": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] + "type": "header-custom", + // [!code focus:18] + "settings": { + "client": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ], + "server": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + } } ``` @@ -236,14 +256,30 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 ```json { - "header": "", // dns dtls srtp utp wechat wireguard - "value": "" // password domain + "type": "mkcp-legacy", + // [!code focus:4] + "settings": { + "header": "", // dns dtls srtp utp wechat wireguard + "value": "" // password domain + } } ``` -`header`: empty for original & aes128gcm +旧 mKCP 的包头伪装/混淆,`value` 的含义随 `header` 变化。注意伪造只是简单的包头伪造,不代表实现了完整协议。 -`value`: empty for original +> 为空时: 进行 AES-128-GCM 加密,`value` 为其密码,若 `value` 为空则改为使用默认的简单 xor 混淆。 + +> `dns`: 伪造为 DNS 查询,`value` 为指定的域名,为空时默认 `www.baidu.com`。 + +> `dtls`: 伪造为 DTLS 1.2 应用数据,`value` 无作用。 + +> `srtp`: 伪造为 SRTP。`value` 无作用。 + +> `utp`: 伪造为 uTP(BitTorrent)。`value` 无作用。 + +> `wechat`: 伪造为微信视频通话。`value` 无作用。 + +> `wireguard`: 伪造为 WireGuard。`value` 无作用。 ### noise @@ -251,16 +287,20 @@ FinalMask 在核心处理完包括 TLS/REALITY 在内的传输层加密后,对 ```json { - "reset": "30-60", - "noise": [ - { - "rand": "1-8192", - "randRange": "0-255", - "type": "", - "packet": [], - "delay": "10-20" - } - ] + "type": "noise", + // [!code focus:12] + "settings": { + "reset": "30-60", + "noise": [ + { + "rand": "1-8192", + "randRange": "0-255", + "type": "", + "packet": [], + "delay": "10-20" + } + ] + } } ``` @@ -282,7 +322,11 @@ Salamander 混淆。(来自 Hysteria2) ```json { - "password": "your-password" + "type": "salamander", + // [!code focus:3] + "settings": { + "password": "your-password" + } } ``` @@ -290,14 +334,18 @@ Salamander 混淆。(来自 Hysteria2) ```json { - "password": "", - "ascii": "", + "type": "sudoku", + // [!code focus:10] + "settings": { + "password": "", + "ascii": "", - "customTable": "", - "customTables": [""], + "customTable": "", + "customTables": [""], - "paddingMin": 0, - "paddingMax": 0 + "paddingMin": 0, + "paddingMax": 0 + } } ``` @@ -317,8 +365,12 @@ Salamander 混淆。(来自 Hysteria2) ```json { - "domains": ["t.example.com"], - "resolvers": ["t.example.com+udp://8.8.8.8:53"] + "type": "xdns", + // [!code focus:4] + "settings": { + "domains": ["t.example.com"], + "resolvers": ["t.example.com+udp://8.8.8.8:53"] + } } ``` @@ -332,8 +384,12 @@ Salamander 混淆。(来自 Hysteria2) ```json { - "dgram": false, // optional - "ips": [] // optional + "type": "xicmp", + // [!code focus:4] + "settings": { + "dgram": false, // optional + "ips": [] // optional + } } ``` @@ -347,12 +403,16 @@ Salamander 混淆。(来自 Hysteria2) ```json { - "url": "realm://public@xxx/your-realm-name", - "stunServers": [ - "stun.nextcloud.com:3478", - "global.stun.twilio.com:3478" - ], - "tlsConfig": {} // optional + "type": "realm", + // [!code focus:8] + "settings": { + "url": "realm://public@xxx/your-realm-name", + "stunServers": [ + "stun.nextcloud.com:3478", + "global.stun.twilio.com:3478" + ], + "tlsConfig": {} // optional + } } ``` diff --git a/docs/en/config/transports/finalmask.md b/docs/en/config/transports/finalmask.md index 6e71b770..08954ac0 100644 --- a/docs/en/config/transports/finalmask.md +++ b/docs/en/config/transports/finalmask.md @@ -73,51 +73,57 @@ An array used to camouflage TCP traffic emitted by the core. The first item in t } ``` -> `type`: header-custom | fragment | sudoku +> `type`: string The type of this camouflage layer. -> `settings`: header-custom | fragment | sudoku +> `settings`: string -The concrete settings for this camouflage type. See the fields for each type below. +The concrete settings for this camouflage type. + +See the fields for each type below. ### header-custom ```json { - "clients": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } + "type": "header-custom", + // [!code focus:35] + "settings": { + "clients": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "servers": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "errors": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] ] - ], - "servers": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ], - "errors": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ] + } } ``` @@ -135,10 +141,14 @@ The concrete settings for this camouflage type. See the fields for each type bel ```json { - "packets": "tlshello", - "length": "100-200", - "delay": "10-20", - "maxSplit": "3-6" + "type": "fragment", + // [!code focus:6] + "settings": { + "packets": "tlshello", + "length": "100-200", + "delay": "10-20", + "maxSplit": "3-6" + } } ``` @@ -160,14 +170,18 @@ When it is `0` and `"packets": "tlshello"` is set, the fragmented Client Hello w ```json { - "password": "", - "ascii": "", + "type": "sudoku", + // [!code focus:10] + "settings": { + "password": "", + "ascii": "", - "customTable": "", // field name is custom_table in the upstream documentation - "customTables": [""], // field name is custom_tables in the upstream documentation + "customTable": "", // field name is custom_table in the upstream documentation + "customTables": [""], // field name is custom_tables in the upstream documentation - "paddingMin": 0, // field name is padding_min in the upstream documentation - "paddingMax": 0 // field name is padding_max in the upstream documentation + "paddingMin": 0, // field name is padding_min in the upstream documentation + "paddingMax": 0 // field name is padding_max in the upstream documentation + } } ``` @@ -191,13 +205,15 @@ An array used to camouflage UDP traffic emitted by the core. The first item in t } ``` -> `type`: header-custom | header-dns | header-dtls | header-srtp | header-utp | header-wechat | header-wireguard | mkcp-original | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp +> `type`: string The type of this camouflage layer. -> `settings`: header-custom | header-dns | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp +> `settings`: string -The concrete settings for this camouflage type. See the fields for each type below. +The concrete settings for this camouflage type. + +See the fields for each type below. ### header-custom @@ -205,22 +221,26 @@ Always merged into the packet header. ```json { - "client": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ], - "server": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] + "type": "header-custom", + // [!code focus:18] + "settings": { + "client": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ], + "server": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + } } ``` @@ -236,14 +256,30 @@ Always merged into the packet header. ```json { - "header": "", // dns dtls srtp utp wechat wireguard - "value": "" // password domain + "type": "mkcp-legacy", + // [!code focus:4] + "settings": { + "header": "", // dns dtls srtp utp wechat wireguard + "value": "" // password domain + } } ``` -`header`: empty for original & aes128gcm +Legacy mKCP packet-header camouflage/obfuscation. The meaning of `value` depends on `header`. Note that the forgery is only a simple packet-header forgery and does not mean the full protocol is implemented. -`value`: empty for original +> When empty: applies AES-128-GCM encryption with `value` as the password. If `value` is empty, it falls back to the default simple XOR obfuscation. + +> `dns`: forged as a DNS query. `value` is the specified domain; defaults to `www.baidu.com` when empty. + +> `dtls`: forged as DTLS 1.2 application data. `value` has no effect. + +> `srtp`: forged as SRTP. `value` has no effect. + +> `utp`: forged as uTP (BitTorrent). `value` has no effect. + +> `wechat`: forged as a WeChat video call. `value` has no effect. + +> `wireguard`: forged as WireGuard. `value` has no effect. ### noise @@ -251,16 +287,20 @@ Noise sent before the actual data. ```json { - "reset": "30-60", - "noise": [ - { - "rand": "1-8192", - "randRange": "0-255", - "type": "", - "packet": [], - "delay": "10-20" - } - ] + "type": "noise", + // [!code focus:12] + "settings": { + "reset": "30-60", + "noise": [ + { + "rand": "1-8192", + "randRange": "0-255", + "type": "", + "packet": [], + "delay": "10-20" + } + ] + } } ``` @@ -282,7 +322,11 @@ Salamander obfuscation. From Hysteria2. ```json { - "password": "your-password" + "type": "salamander", + // [!code focus:3] + "settings": { + "password": "your-password" + } } ``` @@ -290,14 +334,18 @@ Salamander obfuscation. From Hysteria2. ```json { - "password": "", - "ascii": "", + "type": "sudoku", + // [!code focus:10] + "settings": { + "password": "", + "ascii": "", - "customTable": "", - "customTables": [""], + "customTable": "", + "customTables": [""], - "paddingMin": 0, - "paddingMax": 0 + "paddingMin": 0, + "paddingMax": 0 + } } ``` @@ -317,8 +365,12 @@ For example, if you own `example.com`, set an A record like `a.example.com` to t ```json { - "domains": ["t.example.com"], - "resolvers": ["t.example.com+udp://8.8.8.8:53"] + "type": "xdns", + // [!code focus:4] + "settings": { + "domains": ["t.example.com"], + "resolvers": ["t.example.com+udp://8.8.8.8:53"] + } } ``` @@ -332,8 +384,12 @@ At least one of `domains` and `resolvers` must be set. ```json { - "dgram": false, // optional - "ips": [] // optional + "type": "xicmp", + // [!code focus:4] + "settings": { + "dgram": false, // optional + "ips": [] // optional + } } ``` @@ -347,12 +403,16 @@ Self-built https://github.com/apernet/hysteria-realm-server ```json { - "url": "realm://public@xxx/your-realm-name", - "stunServers": [ - "stun.nextcloud.com:3478", - "global.stun.twilio.com:3478" - ], - "tlsConfig": {} // optional + "type": "realm", + // [!code focus:8] + "settings": { + "url": "realm://public@xxx/your-realm-name", + "stunServers": [ + "stun.nextcloud.com:3478", + "global.stun.twilio.com:3478" + ], + "tlsConfig": {} // optional + } } ``` diff --git a/docs/ru/config/transports/finalmask.md b/docs/ru/config/transports/finalmask.md index 3ebe60b7..d36bf837 100644 --- a/docs/ru/config/transports/finalmask.md +++ b/docs/ru/config/transports/finalmask.md @@ -73,51 +73,57 @@ FinalMask добавляет последний слой маскировки п } ``` -> `type`: header-custom | fragment | sudoku +> `type`: string Тип этого слоя маскировки. -> `settings`: header-custom | fragment | sudoku +> `settings`: string -Конкретные настройки для этого типа маскировки. Поля каждого типа приведены ниже. +Конкретные настройки для этого типа маскировки. + +Поля каждого типа приведены ниже. ### header-custom ```json { - "clients": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } + "type": "header-custom", + // [!code focus:35] + "settings": { + "clients": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "servers": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + ], + "errors": [ + [ + { + "delay": 0, + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] ] - ], - "servers": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ], - "errors": [ - [ - { - "delay": 0, - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] - ] + } } ``` @@ -135,10 +141,14 @@ FinalMask добавляет последний слой маскировки п ```json { - "packets": "tlshello", - "length": "100-200", - "delay": "10-20", - "maxSplit": "3-6" + "type": "fragment", + // [!code focus:6] + "settings": { + "packets": "tlshello", + "length": "100-200", + "delay": "10-20", + "maxSplit": "3-6" + } } ``` @@ -160,14 +170,18 @@ FinalMask добавляет последний слой маскировки п ```json { - "password": "", - "ascii": "", + "type": "sudoku", + // [!code focus:10] + "settings": { + "password": "", + "ascii": "", - "customTable": "", // в upstream-документации поле называется custom_table - "customTables": [""], // в upstream-документации поле называется custom_tables + "customTable": "", // в upstream-документации поле называется custom_table + "customTables": [""], // в upstream-документации поле называется custom_tables - "paddingMin": 0, // в upstream-документации поле называется padding_min - "paddingMax": 0 // в upstream-документации поле называется padding_max + "paddingMin": 0, // в upstream-документации поле называется padding_min + "paddingMax": 0 // в upstream-документации поле называется padding_max + } } ``` @@ -191,13 +205,15 @@ FinalMask добавляет последний слой маскировки п } ``` -> `type`: header-custom | header-dns | header-dtls | header-srtp | header-utp | header-wechat | header-wireguard | mkcp-original | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp +> `type`: string Тип этого слоя маскировки. -> `settings`: header-custom | header-dns | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp +> `settings`: string -Конкретные настройки для этого типа маскировки. Поля каждого типа приведены ниже. +Конкретные настройки для этого типа маскировки. + +Поля каждого типа приведены ниже. ### header-custom @@ -205,22 +221,26 @@ FinalMask добавляет последний слой маскировки п ```json { - "client": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ], - "server": [ - { - "rand": 0, - "randRange": "0-255", - "type": "", - "packet": [] - } - ] + "type": "header-custom", + // [!code focus:18] + "settings": { + "client": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ], + "server": [ + { + "rand": 0, + "randRange": "0-255", + "type": "", + "packet": [] + } + ] + } } ``` @@ -236,14 +256,30 @@ FinalMask добавляет последний слой маскировки п ```json { - "header": "", // dns dtls srtp utp wechat wireguard - "value": "" // password domain + "type": "mkcp-legacy", + // [!code focus:4] + "settings": { + "header": "", // dns dtls srtp utp wechat wireguard + "value": "" // password domain + } } ``` -`header`: empty for original & aes128gcm +Маскировка/обфускация заголовка пакетов в стиле старого mKCP. Значение `value` зависит от `header`. Обратите внимание: подделка - это лишь простая подделка заголовка пакета и не означает реализацию полного протокола. -`value`: empty for original +> Когда пусто: применяется шифрование AES-128-GCM, где `value` - пароль. Если `value` пусто, вместо этого используется простая XOR-обфускация по умолчанию. + +> `dns`: подделка под DNS-запрос. `value` - указанный домен; при пустом значении по умолчанию `www.baidu.com`. + +> `dtls`: подделка под данные приложения DTLS 1.2. `value` не используется. + +> `srtp`: подделка под SRTP. `value` не используется. + +> `utp`: подделка под uTP (BitTorrent). `value` не используется. + +> `wechat`: подделка под видеозвонок WeChat. `value` не используется. + +> `wireguard`: подделка под WireGuard. `value` не используется. ### noise @@ -251,16 +287,20 @@ FinalMask добавляет последний слой маскировки п ```json { - "reset": "30-60", - "noise": [ - { - "rand": "1-8192", - "randRange": "0-255", - "type": "", - "packet": [], - "delay": "10-20" - } - ] + "type": "noise", + // [!code focus:12] + "settings": { + "reset": "30-60", + "noise": [ + { + "rand": "1-8192", + "randRange": "0-255", + "type": "", + "packet": [], + "delay": "10-20" + } + ] + } } ``` @@ -282,7 +322,11 @@ FinalMask добавляет последний слой маскировки п ```json { - "password": "your-password" + "type": "salamander", + // [!code focus:3] + "settings": { + "password": "your-password" + } } ``` @@ -290,14 +334,18 @@ FinalMask добавляет последний слой маскировки п ```json { - "password": "", - "ascii": "", + "type": "sudoku", + // [!code focus:10] + "settings": { + "password": "", + "ascii": "", - "customTable": "", - "customTables": [""], + "customTable": "", + "customTables": [""], - "paddingMin": 0, - "paddingMax": 0 + "paddingMin": 0, + "paddingMax": 0 + } } ``` @@ -317,8 +365,12 @@ FinalMask добавляет последний слой маскировки п ```json { - "domains": ["t.example.com"], - "resolvers": ["t.example.com+udp://8.8.8.8:53"] + "type": "xdns", + // [!code focus:4] + "settings": { + "domains": ["t.example.com"], + "resolvers": ["t.example.com+udp://8.8.8.8:53"] + } } ``` @@ -332,8 +384,12 @@ FinalMask добавляет последний слой маскировки п ```json { - "dgram": false, // optional - "ips": [] // optional + "type": "xicmp", + // [!code focus:4] + "settings": { + "dgram": false, // optional + "ips": [] // optional + } } ``` @@ -347,12 +403,16 @@ FinalMask добавляет последний слой маскировки п ```json { - "url": "realm://public@xxx/your-realm-name", - "stunServers": [ - "stun.nextcloud.com:3478", - "global.stun.twilio.com:3478" - ], - "tlsConfig": {} // optional + "type": "realm", + // [!code focus:8] + "settings": { + "url": "realm://public@xxx/your-realm-name", + "stunServers": [ + "stun.nextcloud.com:3478", + "global.stun.twilio.com:3478" + ], + "tlsConfig": {} // optional + } } ```