Skip to content

Commit

Permalink
feat: support dialer-proxy and smux property in clash.meta config
Browse files Browse the repository at this point in the history
  • Loading branch information
geekdada committed May 22, 2024
1 parent a739104 commit 64c9575
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 4 deletions.
6 changes: 3 additions & 3 deletions docs/guide/custom-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ Surgio 不会验证名称是否有效
:::

- sing-box 的多路复用说明:[链接](https://sing-box.sagernet.org/configuration/shared/multiplex/)
- 【暂不支持】mihomo 的多路复用说明:[链接](https://wiki.metacubex.one/config/proxies/sing-mux/)
- Clash Meta (mihomo) 的多路复用说明:[链接](https://wiki.metacubex.one/config/proxies/sing-mux/)

```json5
{
Expand Down Expand Up @@ -996,9 +996,9 @@ module.exports = {
- 类型: `string`
- 默认值: `undefined`

是否对当前 Provider 中所有节点使用自定义 [Underlying Proxy](https://manual.nssurge.com/policy/proxy.html)。在 `CustomProvider` 中也可以使用,但是优先级低于 `nodeConfig.underlyingProxy`。
是否对当前 Provider 中所有节点使用自定义 Underlying Proxy。在 `CustomProvider` 中也可以使用,但是优先级低于 `nodeConfig.underlyingProxy`

目前仅 Surge 支持该特性。
目前仅 [Surge](https://manual.nssurge.com/policy/proxy.html) 和 [Clash Meta](https://wiki.metacubex.one/config/proxies/dialer-proxy/?h=dialer#dialer-proxy) 支持该特性。

:::warning 注意
Surgio 不会验证名称是否有效
Expand Down
63 changes: 63 additions & 0 deletions src/utils/__tests__/clash.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -988,4 +988,67 @@ test('getClashNodes', async (t) => {
},
],
)

t.deepEqual(
clash.getClashNodes([
{
nodeName: 'trojan',
type: NodeTypeEnum.Trojan,
hostname: '1.1.1.1',
port: 443,
password: 'password1',
udpRelay: true,
alpn: ['h2', 'http/1.1'],
sni: 'example.com',
skipCertVerify: true,
network: 'ws',
underlyingProxy: 'socks5',
multiplex: {
protocol: 'smux',
maxConnections: 10,
minStreams: 1,
maxStreams: 16,
padding: true,
brutal: {
upMbps: 100,
downMbps: 100,
},
},
clashConfig: {
clashCore: 'clash.meta',
},
},
]),
[
{
alpn: ['h2', 'http/1.1'],
'dialer-proxy': 'socks5',
name: 'trojan',
network: 'ws',
password: 'password1',
port: 443,
server: '1.1.1.1',
'skip-cert-verify': true,
smux: {
'brutal-opts': {
down: 100,
enabled: true,
up: 100,
},
enabled: true,
'max-connections': 10,
'max-streams': 16,
'min-streams': 1,
padding: true,
protocol: 'smux',
},
sni: 'example.com',
type: 'trojan',
udp: true,
'ws-opts': {
path: '/',
},
},
],
)
})
38 changes: 37 additions & 1 deletion src/utils/clash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,43 @@ export const getClashNodes = function (
filter?: NodeFilterType | SortedNodeFilterType,
) {
return applyFilter(list, filter)
.map(nodeListMapper)
.map((nodeConfig) => {
const clashNode = nodeListMapper(nodeConfig)

if (!clashNode) {
return clashNode
}

if (nodeConfig?.clashConfig?.clashCore === 'clash.meta') {
if (nodeConfig.underlyingProxy) {
clashNode['dialer-proxy'] = nodeConfig.underlyingProxy
}

if ('multiplex' in nodeConfig && nodeConfig.multiplex) {
// https://wiki.metacubex.one/config/proxies/sing-mux/#sing-mux
clashNode.smux = {
enabled: true,
protocol: nodeConfig.multiplex.protocol,
...(nodeConfig.multiplex.brutal && {
'brutal-opts': {
enabled: true,
up: nodeConfig.multiplex.brutal.upMbps,
down: nodeConfig.multiplex.brutal.downMbps,
},
}),
...pickAndFormatKeys(
nodeConfig.multiplex,
['maxConnections', 'minStreams', 'maxStreams', 'padding'],
{
keyFormat: 'kebabCase',
},
),
}
}
}

return clashNode
})
.filter((item): item is NonNullable<ReturnType<typeof nodeListMapper>> =>
checkNotNullish(item),
)
Expand Down
18 changes: 18 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,24 @@ export const pickAndFormatStringList = (
return result
}

/**
* Pick and format keys from an object
* Input:
* {
* foo: 'bar',
* bAr: 'bar',
* bAz: 'baz',
* }
*
* pickAndFormatKeys(obj, ['foo', 'bar'], { keyFormat: 'kebabCase' })
*
* Output:
* {
* 'foo': 'bar',
* 'b-ar': 'bar',
* 'b-az': 'baz',
* }
*/
export const pickAndFormatKeys = (
obj: Record<string, any>,
keyList: readonly string[],
Expand Down

0 comments on commit 64c9575

Please sign in to comment.