mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-01 10:45:00 +03:00
feat(xray): add loopback sniffing and per-segment fragment masks
- Loopback outbound: add sniffing support (xray-core #6320) - FinalMask fragment: support per-segment lengths/delays arrays with legacy length/delay migration (xray-core #6334) - Consolidate sniffing into a shared SniffingFields component and the canonical SniffingSchema across inbound, VLESS reverse, and loopback
This commit is contained in:
@@ -23,9 +23,6 @@ export const VlessClientSchema = z.object({
|
||||
subId: z.string().default(''),
|
||||
comment: z.string().default(''),
|
||||
reset: z.number().int().min(0).default(0),
|
||||
// VLESS simple reverse-proxy: which reverse tag this client routes to,
|
||||
// plus an optional sniffing override for that path. Distinct from the
|
||||
// inbound-level `fallbacks` feature.
|
||||
reverse: z
|
||||
.object({
|
||||
tag: z.string(),
|
||||
@@ -42,9 +39,6 @@ export const VlessInboundSettingsSchema = z.object({
|
||||
decryption: z.string().min(1).default('none'),
|
||||
encryption: z.string().min(1).default('none'),
|
||||
fallbacks: z.array(VlessFallbackSchema).default([]),
|
||||
// TODO: narrow to flow === 'xtls-rprx-vision' once a per-flow discriminator
|
||||
// exists. 4-positive-int padding seed for xtls-rprx-vision; backend uses
|
||||
// safe defaults when omitted.
|
||||
testseed: z.array(z.number().int().positive()).length(4).optional(),
|
||||
});
|
||||
export type VlessInboundSettings = z.infer<typeof VlessInboundSettingsSchema>;
|
||||
|
||||
@@ -26,10 +26,6 @@ export * from './vless';
|
||||
export * from './vmess';
|
||||
export * from './wireguard';
|
||||
|
||||
// Outbound discriminated union spans 13 protocols (mixed/tunnel are
|
||||
// inbound-only; freedom/blackhole/dns/loopback are outbound-only). The wire
|
||||
// shape is `{ protocol, settings }` — same wrapper pattern as the inbound
|
||||
// union, even though some leaf schemas (freedom, blackhole) are sparse.
|
||||
export const OutboundSettingsSchema = z.discriminatedUnion('protocol', [
|
||||
z.object({ protocol: z.literal('vmess'), settings: VmessOutboundSettingsSchema }),
|
||||
z.object({ protocol: z.literal('vless'), settings: VlessOutboundSettingsSchema }),
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
// Loopback outbound reinjects traffic back into a named inbound for chained
|
||||
// routing. The single `inboundTag` field references an inbound tag by name.
|
||||
import { SniffingSchema } from '@/schemas/primitives';
|
||||
|
||||
export const LoopbackOutboundSettingsSchema = z.object({
|
||||
inboundTag: z.string().optional(),
|
||||
sniffing: SniffingSchema.optional(),
|
||||
});
|
||||
export type LoopbackOutboundSettings = z.infer<typeof LoopbackOutboundSettingsSchema>;
|
||||
|
||||
@@ -2,9 +2,6 @@ import { z } from 'zod';
|
||||
|
||||
import { PortSchema } from '@/schemas/primitives';
|
||||
|
||||
// Trojan outbound persists as { servers: [{ address, port, password }] }
|
||||
// — distinct from VLESS outbound which stores the connect target flat at
|
||||
// the settings root. The wrapping mirrors what Xray expects.
|
||||
export const TrojanOutboundServerSchema = z.object({
|
||||
address: z.string().min(1),
|
||||
port: PortSchema,
|
||||
|
||||
@@ -3,9 +3,6 @@ import { z } from 'zod';
|
||||
import { PortSchema } from '@/schemas/primitives';
|
||||
import { VmessSecuritySchema } from '@/schemas/protocols/shared/vmess';
|
||||
|
||||
// Vmess outbound persists in the standard Xray `vnext` shape:
|
||||
// { vnext: [{ address, port, users: [{ id, security }] }] }
|
||||
// — distinct from VLESS outbound which the panel stores flat.
|
||||
export const VmessOutboundUserSchema = z.object({
|
||||
id: z.uuid(),
|
||||
security: VmessSecuritySchema.default('auto'),
|
||||
|
||||
@@ -9,8 +9,6 @@ export const WireguardDomainStrategySchema = z.enum([
|
||||
]);
|
||||
export type WireguardDomainStrategy = z.infer<typeof WireguardDomainStrategySchema>;
|
||||
|
||||
// Outbound peer is the remote server we connect to: no privateKey, but an
|
||||
// `endpoint` (host:port) the inbound side does not need.
|
||||
export const WireguardOutboundPeerSchema = z.object({
|
||||
publicKey: z.string().min(1),
|
||||
preSharedKey: z.string().optional(),
|
||||
@@ -20,9 +18,6 @@ export const WireguardOutboundPeerSchema = z.object({
|
||||
});
|
||||
export type WireguardOutboundPeer = z.infer<typeof WireguardOutboundPeerSchema>;
|
||||
|
||||
// Wire format: address is a string[] (Xray expects an array even though the
|
||||
// panel UI stores it comma-joined); reserved is number[] (panel splits the
|
||||
// comma string and Number()-coerces each entry).
|
||||
export const WireguardOutboundSettingsSchema = z.object({
|
||||
mtu: z.number().int().min(1).optional(),
|
||||
secretKey: z.string().min(1),
|
||||
|
||||
Reference in New Issue
Block a user