Skip to content

Commit

Permalink
feat: add support for trojan web-socket config
Browse files Browse the repository at this point in the history
- Parsing
  - Clash subscription
- Generating
  - Surge
  - Clash
  • Loading branch information
geekdada committed Mar 18, 2022
1 parent 097c1df commit 394f65d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 8 deletions.
10 changes: 9 additions & 1 deletion lib/provider/ClashProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,11 @@ export const parseClashConfig = (
'udp-relay': resolveUdpRelay(item.udp, udpRelay),
} as ShadowsocksrNodeConfig;

case 'trojan':
case 'trojan': {
const network = item.network;
const wsOpts = _.get(item, 'ws-opts', {});
const wsHeaders = lowercaseHeaderKeys(_.get(wsOpts, 'headers', {}));

return {
type: NodeTypeEnum.Trojan,
nodeName: item.name,
Expand All @@ -337,7 +341,11 @@ export const parseClashConfig = (
...('sni' in item ? { sni: item.sni } : null),
'udp-relay': resolveUdpRelay(item.udp, udpRelay),
tls13: tls13 ?? false,
...(network === 'ws'
? { network: 'ws', wsPath: _.get(wsOpts, 'path', '/'), wsHeaders }
: null),
} as TrojanNodeConfig;
}

default:
logger.warn(
Expand Down
3 changes: 3 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ export interface TrojanNodeConfig extends SimpleNodeConfig {
readonly sni?: string;
readonly 'udp-relay'?: boolean;
readonly tls13?: boolean;
readonly network?: 'default' | 'ws';
readonly wsPath?: string;
readonly wsHeaders?: Record<string, string>;
}

export interface Socks5NodeConfig extends SimpleNodeConfig {
Expand Down
30 changes: 23 additions & 7 deletions lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { ConfigCache } from './cache';
import { ERR_INVALID_FILTER, OBFS_UA } from '../constant';
import { validateFilter } from './filter';
import httpClient from './http-client';
import { getSurgeExtendHeaders } from './surge';
import { formatVmessUri } from './v2ray';

const logger = createLogger({ service: 'surgio:utils' });
Expand Down Expand Up @@ -369,19 +370,13 @@ export const getSurgeNodes = function (
configList.push(`encrypt-method=${config.method}`);
}

function getHeader(wsHeaders: Record<string, string>): string {
return Object.keys(wsHeaders)
.map((headerKey) => `${headerKey}:${wsHeaders[headerKey]}`)
.join('|');
}

if (config.network === 'ws') {
configList.push('ws=true');
configList.push(`ws-path=${config.path}`);
configList.push(
'ws-headers=' +
JSON.stringify(
getHeader({
getSurgeExtendHeaders({
host: config.host || config.hostname,
'user-agent': OBFS_UA,
..._.omit(config.wsHeaders, ['host']), // host 本质上是一个头信息,所以可能存在冲突的情况。以 host 属性为准。
Expand Down Expand Up @@ -501,6 +496,18 @@ export const getSurgeNodes = function (
: []),
];

if (nodeConfig.network === 'ws') {
configList.push('ws=true');
configList.push(`ws-path=${nodeConfig.wsPath}`);

if (nodeConfig.wsHeaders) {
configList.push(
'ws-headers=' +
JSON.stringify(getSurgeExtendHeaders(nodeConfig.wsHeaders)),
);
}
}

return [nodeConfig.nodeName, configList.join(', ')].join(' = ');
}

Expand Down Expand Up @@ -729,6 +736,15 @@ export const getClashNodes = function (
...(nodeConfig.alpn ? { alpn: nodeConfig.alpn } : null),
...(nodeConfig.sni ? { sni: nodeConfig.sni } : null),
'skip-cert-verify': nodeConfig.skipCertVerify === true,
...(nodeConfig.network === 'ws'
? {
network: 'ws',
'ws-opts': {
path: nodeConfig.wsPath || '/',
...nodeConfig.wsHeaders,
},
}
: null),
};

case NodeTypeEnum.Socks5: {
Expand Down
7 changes: 7 additions & 0 deletions lib/utils/surge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const getSurgeExtendHeaders = (
wsHeaders: Record<string, string>,
): string => {
return Object.keys(wsHeaders)
.map((headerKey) => `${headerKey}:${wsHeaders[headerKey]}`)
.join('|');
};

0 comments on commit 394f65d

Please sign in to comment.