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 { parseSS, type ParsedNode } from './ss.js';
|
||||||
import { parseVMess } from './vmess.js';
|
import { parseVMess } from './vmess.js';
|
||||||
import { parseTrojan } from './trojan.js';
|
import { parseTrojan } from './trojan.js';
|
||||||
|
import { parseVless } from './vless.js';
|
||||||
|
|
||||||
export type { ParsedNode };
|
export type { ParsedNode };
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ export function parseNodeUri(uri: string): ParsedNode | null {
|
|||||||
if (uri.startsWith('ss://')) return parseSS(uri);
|
if (uri.startsWith('ss://')) return parseSS(uri);
|
||||||
if (uri.startsWith('vmess://')) return parseVMess(uri);
|
if (uri.startsWith('vmess://')) return parseVMess(uri);
|
||||||
if (uri.startsWith('trojan://')) return parseTrojan(uri);
|
if (uri.startsWith('trojan://')) return parseTrojan(uri);
|
||||||
|
if (uri.startsWith('vless://')) return parseVless(uri);
|
||||||
return null;
|
return null;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
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 };
|
||||||
|
}
|
||||||
@@ -50,7 +50,7 @@ export default function StaticNodes() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2 style={styles.title}>静态节点</h2>
|
<h2 style={styles.title}>静态节点</h2>
|
||||||
<p style={styles.subtitle}>粘贴 ss:// / vmess:// / trojan:// URI 自动解析</p>
|
<p style={styles.subtitle}>粘贴 ss:// / vmess:// / trojan:// / vless:// URI 自动解析</p>
|
||||||
|
|
||||||
<div style={styles.form}>
|
<div style={styles.form}>
|
||||||
<input
|
<input
|
||||||
@@ -60,7 +60,7 @@ export default function StaticNodes() {
|
|||||||
style={{ width: 180 }}
|
style={{ width: 180 }}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
placeholder="粘贴节点 URI(ss:// / vmess:// / trojan://)"
|
placeholder="粘贴节点 URI(ss:// / vmess:// / trojan:// / vless://)"
|
||||||
value={uri}
|
value={uri}
|
||||||
onChange={e => setUri(e.target.value)}
|
onChange={e => setUri(e.target.value)}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
|
|||||||
Reference in New Issue
Block a user