mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-27 08:15:01 +03:00
d8221a8153
The Host VLESS Route field was stored and shown in the panel but never applied to any generated subscription (raw, JSON, Clash), so the UUID was emitted unmodified (#5655). Xray reads the route from the UUID's 3rd group (bytes 6-7, net.PortFromBytes) and masks those bytes to zero before authenticating, so a value can be baked into the share/JSON/Clash UUIDs without breaking the user match. A shared applyVlessRoute helper encodes a single 0-65535 value as the 3rd group; empty/invalid/non-UUID input is left unchanged, so legacy data never yields a broken link and no DB migration is needed. The field was wrongly validated as a multi-segment port spec (that form belongs to the separate server-side routing rule). It is now a single value 0-65535, with frontend validation, link-preview parity (genVlessLink/hostToExternalProxyEntry), hint + error translations across all 13 locales, and tests on every path. Closes #5655
31 lines
1.2 KiB
TypeScript
31 lines
1.2 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
import { PortSchema } from '@/schemas/primitives';
|
|
|
|
import { AlpnSchema, UtlsFingerprintSchema } from '@/schemas/protocols/security/tls';
|
|
|
|
export const ExternalProxyForceTlsSchema = z.enum(['same', 'tls', 'none']);
|
|
export type ExternalProxyForceTls = z.infer<typeof ExternalProxyForceTlsSchema>;
|
|
|
|
// An inbound can advertise external proxy fronts (CDN edges, mirror nodes)
|
|
// that share its config but vary the dest+port+SNI for the share link. The
|
|
// panel form ships rows of this shape; link generators iterate them when
|
|
// stream.externalProxy is non-empty.
|
|
export const ExternalProxyEntrySchema = z.object({
|
|
forceTls: ExternalProxyForceTlsSchema.default('same'),
|
|
dest: z.string().default(''),
|
|
port: PortSchema.default(443),
|
|
remark: z.string().default(''),
|
|
sni: z.string().optional(),
|
|
fingerprint: z.preprocess(
|
|
(val) => (val === '' ? undefined : val),
|
|
UtlsFingerprintSchema.optional(),
|
|
),
|
|
alpn: z.array(AlpnSchema).optional(),
|
|
pinnedPeerCertSha256: z.array(z.string()).optional(),
|
|
verifyPeerCertByName: z.string().optional(),
|
|
echConfigList: z.string().optional(),
|
|
vlessRoute: z.string().optional(),
|
|
});
|
|
export type ExternalProxyEntry = z.infer<typeof ExternalProxyEntrySchema>;
|