Skip to content

Commit d90d380

Browse files
feat(settings): hev TUN engine option + tuning controls
- TunEngineSection offers hev for both cores (sing-box gains a third option, xray a second), and reveals the hev tuning block (UDP mode, connect/rw timeouts, tcp/udp buffers) only when hev is selected. - i18n keys for the new controls across all 8 locales. - regenerated frontend bindings/schemas/defaults for the new enum + settings.
1 parent 95d0d85 commit d90d380

12 files changed

Lines changed: 192 additions & 12 deletions

File tree

frontend/src/features/settings/sections/TunEngineSection.tsx

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
import { Card, SectionLabel, Select } from "../../../components";
2-
import type { CoreEngine, TunEngine } from "../../../generated/bindings";
1+
import { Card, Field, SectionLabel, Select } from "../../../components";
2+
import type { CoreEngine, TunEngine, TunUdpMode } from "../../../generated/bindings";
33
import { useT } from "../../../i18n";
44
import type { AdvancedSettings } from "../../../lib/bridge";
55

66
// Cores the user can pick a TUN engine for, and the engines each may use.
77
// `singbox-tun` (sing-box's own native TUN) is sing-box-only; xray has no native
8-
// tun, so it uses an external engine. Further engines plug in here later.
8+
// tun, so it uses an external engine (tun2socks/hev). Further engines plug in here.
99
const CORES: CoreEngine[] = ["sing-box", "xray"];
1010
const ENGINE_LABEL: Record<TunEngine, string> = {
1111
"singbox-tun": "sing-box TUN",
1212
tun2socks: "tun2socks",
13+
hev: "hev",
1314
};
1415
const ENGINES_FOR: Record<CoreEngine, TunEngine[]> = {
15-
"sing-box": ["singbox-tun", "tun2socks"],
16-
xray: ["tun2socks"],
16+
"sing-box": ["singbox-tun", "tun2socks", "hev"],
17+
xray: ["tun2socks", "hev"],
1718
};
1819

1920
function defaultTunFor(core: CoreEngine): TunEngine {
@@ -35,6 +36,10 @@ export function TunEngineSection({
3536
const setTunFor = (core: CoreEngine, value: TunEngine) =>
3637
set("tunByCore", { ...(settings.tunByCore ?? {}), [core]: value });
3738

39+
// hev is the only engine that reads the tuning knobs below, so only surface them
40+
// when at least one core uses it.
41+
const usesHev = CORES.some((core) => tunFor(core) === "hev");
42+
3843
return (
3944
<>
4045
<SectionLabel>{t("settings.tunEngine")}</SectionLabel>
@@ -63,6 +68,70 @@ export function TunEngineSection({
6368
/>
6469
</div>
6570
))}
71+
72+
{usesHev && (
73+
<div
74+
style={{ marginTop: 12, borderTop: "1px solid var(--outline-faint)", paddingTop: 12 }}
75+
>
76+
<div style={{ fontSize: 11.5, color: "var(--on-surface-faint)", marginBottom: 10 }}>
77+
{t("settings.tunHevTuning")}
78+
</div>
79+
<div
80+
style={{
81+
display: "flex",
82+
alignItems: "center",
83+
justifyContent: "space-between",
84+
gap: 12,
85+
padding: "5px 0",
86+
}}
87+
>
88+
<span style={{ fontSize: 13.5, color: "var(--on-surface)" }}>
89+
{t("settings.tunUdpMode")}
90+
</span>
91+
<Select
92+
style={{ width: 150, flex: "0 0 auto" }}
93+
value={settings.tunUdpMode}
94+
onChange={(v) => set("tunUdpMode", v as TunUdpMode)}
95+
options={[
96+
{ value: "udp", label: "UDP" },
97+
{ value: "tcp", label: "TCP" },
98+
]}
99+
/>
100+
</div>
101+
<div style={{ padding: "8px 4px 0" }}>
102+
<Field
103+
label={t("settings.tunConnectTimeout")}
104+
value={settings.tunConnectTimeoutMs}
105+
type="number"
106+
onChange={(value) => set("tunConnectTimeoutMs", Number(value))}
107+
/>
108+
<Field
109+
label={t("settings.tunTcpRwTimeout")}
110+
value={settings.tunTcpRwTimeoutMs}
111+
type="number"
112+
onChange={(value) => set("tunTcpRwTimeoutMs", Number(value))}
113+
/>
114+
<Field
115+
label={t("settings.tunUdpRwTimeout")}
116+
value={settings.tunUdpRwTimeoutMs}
117+
type="number"
118+
onChange={(value) => set("tunUdpRwTimeoutMs", Number(value))}
119+
/>
120+
<Field
121+
label={t("settings.tunTcpBuffer")}
122+
value={settings.tunTcpBufferSize}
123+
type="number"
124+
onChange={(value) => set("tunTcpBufferSize", Number(value))}
125+
/>
126+
<Field
127+
label={t("settings.tunUdpRecvBuffer")}
128+
value={settings.tunUdpRecvBufferSize}
129+
type="number"
130+
onChange={(value) => set("tunUdpRecvBufferSize", Number(value))}
131+
/>
132+
</div>
133+
</div>
134+
)}
66135
</Card>
67136
</>
68137
);

frontend/src/generated/bindings.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ export type AdvancedSettings_Deserialize = {
9393
tunByCore?: Partial<{ [key in CoreEngine]: TunEngine }>,
9494
/** MTU of the TUN interface (sing-box native tun; external engines too). */
9595
tunMtu?: number,
96+
/** UDP relay mode for external TUN engines (hev `socks5.udp`). */
97+
tunUdpMode?: TunUdpMode,
98+
/** Connect timeout (ms) for external TUN engines (hev `misc.connect-timeout`). */
99+
tunConnectTimeoutMs?: number,
100+
/** TCP read/write timeout (ms) (hev `misc.tcp-read-write-timeout`). */
101+
tunTcpRwTimeoutMs?: number,
102+
/** UDP read/write timeout (ms) (hev `misc.udp-read-write-timeout`). */
103+
tunUdpRwTimeoutMs?: number,
104+
/** Per-session TCP buffer size in bytes (hev `misc.tcp-buffer-size`). */
105+
tunTcpBufferSize?: number,
106+
/** UDP receive buffer (SO_RCVBUF) size in bytes (hev `misc.udp-recv-buffer-size`). */
107+
tunUdpRecvBufferSize?: number,
96108
};
97109

98110
/**
@@ -146,6 +158,18 @@ export type AdvancedSettings_Serialize = {
146158
tunByCore: Partial<{ [key in CoreEngine]: TunEngine }>,
147159
/** MTU of the TUN interface (sing-box native tun; external engines too). */
148160
tunMtu: number,
161+
/** UDP relay mode for external TUN engines (hev `socks5.udp`). */
162+
tunUdpMode: TunUdpMode,
163+
/** Connect timeout (ms) for external TUN engines (hev `misc.connect-timeout`). */
164+
tunConnectTimeoutMs: number,
165+
/** TCP read/write timeout (ms) (hev `misc.tcp-read-write-timeout`). */
166+
tunTcpRwTimeoutMs: number,
167+
/** UDP read/write timeout (ms) (hev `misc.udp-read-write-timeout`). */
168+
tunUdpRwTimeoutMs: number,
169+
/** Per-session TCP buffer size in bytes (hev `misc.tcp-buffer-size`). */
170+
tunTcpBufferSize: number,
171+
/** UDP receive buffer (SO_RCVBUF) size in bytes (hev `misc.udp-recv-buffer-size`). */
172+
tunUdpRecvBufferSize: number,
149173
};
150174

151175
export type Anytls = {
@@ -874,11 +898,19 @@ export type Tuic = {
874898

875899
/**
876900
* Which engine bridges the TUN device to the proxy core. `SingboxTun` means
877-
* "use sing-box's own native TUN stack" (sing-box core only); `Tun2socks` is an
878-
* external userspace tun→socks process in front of a socks-only core. Further
879-
* engines plug in as new variants. Wire values: `"singbox-tun"`, `"tun2socks"`.
901+
* "use sing-box's own native TUN stack" (sing-box core only); `Tun2socks` and
902+
* `Hev` are external userspace tun→socks processes in front of a socks-only core.
903+
* Further engines plug in as new variants. Wire values: `"singbox-tun"`,
904+
* `"tun2socks"`, `"hev"`.
880905
*/
881-
export type TunEngine = "singbox-tun" | "tun2socks";
906+
export type TunEngine = "singbox-tun" | "tun2socks" | "hev";
907+
908+
/**
909+
* How an external TUN engine relays UDP through the upstream SOCKS5 server: as
910+
* real UDP associations (`udp`) or tunnelled over TCP (`tcp`). Maps to hev's
911+
* `socks5.udp`. Wire values: `"udp"`, `"tcp"`.
912+
*/
913+
export type TunUdpMode = "udp" | "tcp";
882914

883915
export type Vless = {
884916
meta: Meta,

frontend/src/generated/defaults.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,13 @@ export const DEFAULT_ADVANCED_SETTINGS = {
536536
"speedConcurrency": 1,
537537
"strictRoute": false,
538538
"tunByCore": {},
539-
"tunMtu": 9000
539+
"tunConnectTimeoutMs": 10000,
540+
"tunMtu": 9000,
541+
"tunTcpBufferSize": 65536,
542+
"tunTcpRwTimeoutMs": 300000,
543+
"tunUdpMode": "udp",
544+
"tunUdpRecvBufferSize": 524288,
545+
"tunUdpRwTimeoutMs": 60000
540546
} as AdvancedSettings_Serialize;
541547

542548
/* Backend constants (port-test windows, local ports, probe URLs, log rotation). */
@@ -549,7 +555,8 @@ export const DEFAULT_SPEED_TEST_URL = "http://speed.cloudflare.com/__down?bytes=
549555
/* Editor dropdown option lists (wire values, in declaration order). */
550556
export const PROTOCOL_OPTS: Protocol[] = ["vless","vmess","trojan","shadowsocks","socks","http","wireguard","hysteria2","tuic","anytls","naive","shadowtls","custom"];
551557
export const CORE_ENGINE_OPTS: CoreEngine[] = ["xray","sing-box"];
552-
export const TUN_ENGINE_OPTS: string[] = ["singbox-tun","tun2socks"];
558+
export const TUN_ENGINE_OPTS: string[] = ["singbox-tun","tun2socks","hev"];
559+
export const TUN_UDP_MODE_OPTS: string[] = ["udp","tcp"];
553560
export const NETWORK_OPTS: Transport["kind"][] = ["tcp","ws","grpc","httpupgrade","xhttp","h2","kcp","quic"];
554561
export const SECURITY_OPTS: Security[] = ["none","tls","reality"];
555562
export const HEADER_TYPE_OPTS: HeaderType[] = ["none","http","srtp","utp","wechat-video","dtls","wireguard","dns"];

frontend/src/generated/schemas.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { z } from "zod";
22
// This file has been generated by Specta. Do not edit this file manually.
3-
export const TunEngineSchema = z.union([z.literal("singbox-tun"), z.literal("tun2socks")]);
3+
export const TunUdpModeSchema = z.union([z.literal("tcp"), z.literal("udp")]);
4+
export type TunUdpMode = z.infer<typeof TunUdpModeSchema>;
5+
6+
7+
export const TunEngineSchema = z.union([z.literal("hev"), z.literal("singbox-tun"), z.literal("tun2socks")]);
48
export type TunEngine = z.infer<typeof TunEngineSchema>;
59

610

@@ -86,6 +90,12 @@ export const AdvancedSettings_SerializeSchema = z.object({
8690
allowNonLocalhost: z.boolean(),
8791
tunByCore: z.record(CoreEngineSchema, TunEngineSchema),
8892
tunMtu: z.number(),
93+
tunUdpMode: TunUdpModeSchema,
94+
tunConnectTimeoutMs: z.number(),
95+
tunTcpRwTimeoutMs: z.number(),
96+
tunUdpRwTimeoutMs: z.number(),
97+
tunTcpBufferSize: z.number(),
98+
tunUdpRecvBufferSize: z.number(),
8999
});
90100
export type AdvancedSettings_Serialize = z.infer<typeof AdvancedSettings_SerializeSchema>;
91101

@@ -136,6 +146,12 @@ export const AdvancedSettings_DeserializeSchema = z.object({
136146
allowNonLocalhost: z.boolean().optional(),
137147
tunByCore: z.record(CoreEngineSchema, TunEngineSchema).optional(),
138148
tunMtu: z.number().optional(),
149+
tunUdpMode: TunUdpModeSchema.optional(),
150+
tunConnectTimeoutMs: z.number().optional(),
151+
tunTcpRwTimeoutMs: z.number().optional(),
152+
tunUdpRwTimeoutMs: z.number().optional(),
153+
tunTcpBufferSize: z.number().optional(),
154+
tunUdpRecvBufferSize: z.number().optional(),
139155
});
140156
export type AdvancedSettings_Deserialize = z.infer<typeof AdvancedSettings_DeserializeSchema>;
141157

frontend/src/i18n/ar.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,13 @@ const ar = {
465465
"settings.fragmentLength": "طول التجزئة",
466466
"settings.fragmentDelay": "تأخير التجزئة",
467467
"settings.tunMtu": "TUN MTU",
468+
"settings.tunHevTuning": "ضبط hev",
469+
"settings.tunUdpMode": "وضع UDP",
470+
"settings.tunConnectTimeout": "مهلة الاتصال (مللي ثانية)",
471+
"settings.tunTcpRwTimeout": "مهلة قراءة/كتابة TCP (مللي ثانية)",
472+
"settings.tunUdpRwTimeout": "مهلة قراءة/كتابة UDP (مللي ثانية)",
473+
"settings.tunTcpBuffer": "حجم مخزن TCP (بايت)",
474+
"settings.tunUdpRecvBuffer": "مخزن استقبال UDP (بايت)",
468475
"settings.tunEngine": "محرك TUN",
469476
"settings.tunEngineHint":
470477
"المحرك الذي يربط جهاز TUN بكل نواة. يمكن لـ sing-box استخدام TUN الأصلي الخاص به؛ بينما يحتاج xray إلى محرك خارجي.",

frontend/src/i18n/en.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,13 @@ const en = {
400400
"settings.fragmentLength": "Fragment length",
401401
"settings.fragmentDelay": "Fragment delay",
402402
"settings.tunMtu": "TUN MTU",
403+
"settings.tunHevTuning": "hev tuning",
404+
"settings.tunUdpMode": "UDP mode",
405+
"settings.tunConnectTimeout": "Connect timeout (ms)",
406+
"settings.tunTcpRwTimeout": "TCP read/write timeout (ms)",
407+
"settings.tunUdpRwTimeout": "UDP read/write timeout (ms)",
408+
"settings.tunTcpBuffer": "TCP buffer size (bytes)",
409+
"settings.tunUdpRecvBuffer": "UDP receive buffer (bytes)",
403410
"settings.tunEngine": "TUN engine",
404411
"settings.tunEngineHint":
405412
"Which engine bridges the TUN device to each core. sing-box can use its own native TUN; xray needs an external one.",

frontend/src/i18n/es.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,13 @@ const es = {
395395
"settings.fragmentLength": "Longitud de los fragmentos",
396396
"settings.fragmentDelay": "Retardo de fragmentación",
397397
"settings.tunMtu": "MTU de TUN",
398+
"settings.tunHevTuning": "Ajustes de hev",
399+
"settings.tunUdpMode": "Modo UDP",
400+
"settings.tunConnectTimeout": "Tiempo de conexión (ms)",
401+
"settings.tunTcpRwTimeout": "Tiempo lectura/escritura TCP (ms)",
402+
"settings.tunUdpRwTimeout": "Tiempo lectura/escritura UDP (ms)",
403+
"settings.tunTcpBuffer": "Tamaño del búfer TCP (bytes)",
404+
"settings.tunUdpRecvBuffer": "Búfer de recepción UDP (bytes)",
398405
"settings.tunEngine": "Motor TUN",
399406
"settings.tunEngineHint":
400407
"Qué motor conecta el dispositivo TUN con cada núcleo. sing-box puede usar su propio TUN nativo; xray necesita uno externo.",

frontend/src/i18n/hi.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ const hi = {
386386
"settings.fragmentLength": "फ्रैगमेंट लंबाई",
387387
"settings.fragmentDelay": "फ्रैगमेंट विलंब",
388388
"settings.tunMtu": "TUN MTU",
389+
"settings.tunHevTuning": "hev ट्यूनिंग",
390+
"settings.tunUdpMode": "UDP मोड",
391+
"settings.tunConnectTimeout": "कनेक्ट टाइमआउट (ms)",
392+
"settings.tunTcpRwTimeout": "TCP रीड/राइट टाइमआउट (ms)",
393+
"settings.tunUdpRwTimeout": "UDP रीड/राइट टाइमआउट (ms)",
394+
"settings.tunTcpBuffer": "TCP बफ़र आकार (बाइट)",
395+
"settings.tunUdpRecvBuffer": "UDP रिसीव बफ़र (बाइट)",
389396
"settings.tunEngine": "TUN इंजन",
390397
"settings.tunEngineHint":
391398
"कौन सा इंजन TUN डिवाइस को प्रत्येक कोर से जोड़ता है। sing-box अपना नेटिव TUN उपयोग कर सकता है; xray को बाहरी इंजन चाहिए।",

frontend/src/i18n/pt.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,13 @@ const pt = {
394394
"settings.fragmentLength": "Comprimento do fragmento",
395395
"settings.fragmentDelay": "Atraso de fragmentação",
396396
"settings.tunMtu": "MTU do TUN",
397+
"settings.tunHevTuning": "Ajustes do hev",
398+
"settings.tunUdpMode": "Modo UDP",
399+
"settings.tunConnectTimeout": "Tempo de conexão (ms)",
400+
"settings.tunTcpRwTimeout": "Tempo de leitura/escrita TCP (ms)",
401+
"settings.tunUdpRwTimeout": "Tempo de leitura/escrita UDP (ms)",
402+
"settings.tunTcpBuffer": "Tamanho do buffer TCP (bytes)",
403+
"settings.tunUdpRecvBuffer": "Buffer de recepção UDP (bytes)",
397404
"settings.tunEngine": "Motor TUN",
398405
"settings.tunEngineHint":
399406
"Qual motor conecta o dispositivo TUN a cada núcleo. O sing-box pode usar o próprio TUN nativo; o xray precisa de um externo.",

frontend/src/i18n/ru.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,13 @@ const ru = {
415415
"settings.fragmentLength": "Длина фрагмента",
416416
"settings.fragmentDelay": "Задержка фрагментации",
417417
"settings.tunMtu": "TUN MTU",
418+
"settings.tunHevTuning": "Настройки hev",
419+
"settings.tunUdpMode": "Режим UDP",
420+
"settings.tunConnectTimeout": "Таймаут подключения (мс)",
421+
"settings.tunTcpRwTimeout": "Таймаут чтения/записи TCP (мс)",
422+
"settings.tunUdpRwTimeout": "Таймаут чтения/записи UDP (мс)",
423+
"settings.tunTcpBuffer": "Размер буфера TCP (байты)",
424+
"settings.tunUdpRecvBuffer": "Буфер приёма UDP (байты)",
418425
"settings.tunEngine": "Движок TUN",
419426
"settings.tunEngineHint":
420427
"Какой движок связывает TUN-устройство с каждым ядром. sing-box умеет собственный нативный TUN; xray требует внешний.",

0 commit comments

Comments
 (0)