feat: 添加 VLESS-Reality 静态节点解析支持
支持 vless:// URI 解析,覆盖 Reality/TLS/WS/gRPC 传输方式, 自动提取 pbk、sid、sni 等参数生成 Surge 配置行。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { parseSS, type ParsedNode } from './ss.js';
|
||||
import { parseVMess } from './vmess.js';
|
||||
import { parseTrojan } from './trojan.js';
|
||||
import { parseVless } from './vless.js';
|
||||
|
||||
export type { ParsedNode };
|
||||
|
||||
@@ -9,6 +10,7 @@ export function parseNodeUri(uri: string): ParsedNode | null {
|
||||
if (uri.startsWith('ss://')) return parseSS(uri);
|
||||
if (uri.startsWith('vmess://')) return parseVMess(uri);
|
||||
if (uri.startsWith('trojan://')) return parseTrojan(uri);
|
||||
if (uri.startsWith('vless://')) return parseVless(uri);
|
||||
return null;
|
||||
} catch {
|
||||
return null;
|
||||
|
||||
48
server/src/parsers/vless.ts
Normal file
48
server/src/parsers/vless.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import type { ParsedNode } from './ss.js';
|
||||
|
||||
export function parseVless(uri: string): ParsedNode {
|
||||
const url = new URL(uri);
|
||||
const name = decodeURIComponent(url.hash.slice(1)) || 'VLESS';
|
||||
const server = url.hostname;
|
||||
const port = parseInt(url.port, 10);
|
||||
const uuid = url.username;
|
||||
const params = url.searchParams;
|
||||
|
||||
const security = params.get('security') || 'none';
|
||||
const type = params.get('type') || 'tcp';
|
||||
const sni = params.get('sni') || '';
|
||||
const flow = params.get('flow') || '';
|
||||
|
||||
let line = `${name} = vless, ${server}, ${port}, username=${uuid}`;
|
||||
|
||||
if (security === 'reality') {
|
||||
const pbk = params.get('pbk') || '';
|
||||
const sid = params.get('sid') || '';
|
||||
line += ', tls=true';
|
||||
if (sni) line += `, sni=${sni}`;
|
||||
if (pbk) line += `, reality-public-key=${pbk}`;
|
||||
if (sid) line += `, reality-short-id=${sid}`;
|
||||
line += ', skip-cert-verify=false';
|
||||
} else if (security === 'tls') {
|
||||
line += ', tls=true';
|
||||
if (sni) line += `, sni=${sni}`;
|
||||
line += ', skip-cert-verify=false';
|
||||
}
|
||||
|
||||
if (type === 'ws') {
|
||||
const path = params.get('path') || '/';
|
||||
const host = params.get('host') || sni || server;
|
||||
line += ', ws=true';
|
||||
line += `, ws-path=${path}`;
|
||||
line += `, ws-headers=Host:${host}`;
|
||||
} else if (type === 'grpc') {
|
||||
const serviceName = params.get('serviceName') || '';
|
||||
if (serviceName) line += `, grpc-service-name=${serviceName}`;
|
||||
}
|
||||
|
||||
if (flow === 'xtls-rprx-vision') {
|
||||
line += ', flow=xtls-rprx-vision';
|
||||
}
|
||||
|
||||
return { name, type: 'vless', server, port, surgeLine: line };
|
||||
}
|
||||
Reference in New Issue
Block a user