diff --git a/frontend/src/schemas/protocols/stream/xhttp.ts b/frontend/src/schemas/protocols/stream/xhttp.ts index 2d5ec6653..8c8f38602 100644 --- a/frontend/src/schemas/protocols/stream/xhttp.ts +++ b/frontend/src/schemas/protocols/stream/xhttp.ts @@ -17,7 +17,7 @@ export type XHttpMode = z.infer; // are strings because they accept dash-range values like '16-32'. export const XHttpXmuxSchema = z.object({ maxConcurrency: z.string().default('16-32'), - maxConnections: z.union([z.string(), z.number()]).default(0), + maxConnections: z.union([z.string(), z.number()]).default(6), cMaxReuseTimes: z.union([z.string(), z.number()]).default(0), hMaxRequestTimes: z.string().default('600-900'), hMaxReusableSecs: z.string().default('1800-3000'), diff --git a/frontend/src/test/stream-wire-normalize.test.ts b/frontend/src/test/stream-wire-normalize.test.ts index a7a59ada7..81c5db658 100644 --- a/frontend/src/test/stream-wire-normalize.test.ts +++ b/frontend/src/test/stream-wire-normalize.test.ts @@ -11,6 +11,7 @@ import { } from '@/lib/xray/stream-wire-normalize'; import { InboundFormSchema } from '@/schemas/forms/inbound-form'; import type { InboundFormValues } from '@/schemas/forms/inbound-form'; +import { XHttpXmuxSchema } from '@/schemas/protocols/stream/xhttp'; describe('validateRealityTarget', () => { it('accepts host:port and bare port', () => { @@ -150,6 +151,21 @@ describe('normalizeXhttpForWire stream-one', () => { expect(xmux).not.toHaveProperty('maxConcurrency'); expect(xmux.maxConnections).toBe('8'); }); + + it('defaults xmux maxConnections to 6 (xray-core anti-RKN default) and drops maxConcurrency on the wire', () => { + expect(XHttpXmuxSchema.parse({}).maxConnections).toBe(6); + + const out = normalizeXhttpForWire({ + path: '/app', + mode: 'stream-one', + enableXmux: true, + xmux: XHttpXmuxSchema.parse({}), + }, 'outbound'); + + const xmux = out.xmux as Record; + expect(xmux.maxConnections).toBe(6); + expect(xmux).not.toHaveProperty('maxConcurrency'); + }); }); describe('normalizeSockoptForWire', () => {