feat(xray): update xray-core to v26.7.11 and adapt panel

Bump xtls/xray-core to 50231eaf (v26.7.11) and the three binary pins
(DockerInit.sh, release.yml x2) in lockstep.

Adapt the panel to the upstream changes:

- Shadowsocks "none"/"plain" and VMess "none"/"zero" were removed from
  the core. A migration rewrites stored none/plain SS methods to a
  supported cipher and none/zero VMess security to "auto" (on both the
  clients column and inbound settings JSON); the SS build-time heal does
  the same so a row injected after boot cannot brick startup. The removed
  values are dropped from every frontend option list, schema and adapter,
  and coerced to "auto" at the Go link/sub/Clash emit sites and both link
  importers. Fix the CipherType_NONE sentinel that no longer compiles.

- Unencrypted vless/trojan outbounds to a public address are now refused
  by the core. Validate outbounds through the vendored config loader when
  saving the xray template and when storing/merging outbound
  subscriptions, so one such outbound cannot keep the core from starting.

- New TCP finalmask type "xmc" (Minecraft mimicry): add it to the sub
  link allowlist, the frontend enum and the FinalMask form (hostname,
  usernames, required password), and document it.

- streamSettings gained a "method" alias for "network"; canonicalize it
  to "network" at inbound save time and in the form adapters/schema so a
  method-keyed config keeps its transport.

- New root "env" config key is passed through xray.Config, compared in
  Equals, and forces a restart in the hot diff.

- REALITY now defaults minClientVer to 26.3.27; update the form
  placeholder.
This commit is contained in:
MHSanaei
2026-07-12 00:30:47 +02:00
parent affcf6c422
commit 814cda3fb4
39 changed files with 709 additions and 69 deletions
@@ -30,8 +30,6 @@ export const USERS_SECURITY = Object.freeze({
AES_128_GCM: 'aes-128-gcm',
CHACHA20_POLY1305: 'chacha20-poly1305',
AUTO: 'auto',
NONE: 'none',
ZERO: 'zero',
});
export const MODE_OPTION = Object.freeze({
@@ -4,16 +4,16 @@ const VmessSecurityEnum = z.enum([
'aes-128-gcm',
'chacha20-poly1305',
'auto',
'none',
'zero',
]);
// Legacy rows persisted `security: ""` (especially on VMess inbounds
// created before the enum was nailed down). Preprocess maps the empty
// string back to the documented default so existing data parses cleanly
// — subsequent writes serialize the normalized value.
// created before the enum was nailed down), and rows predating xray-core
// v26.7.11 may still hold the removed "none"/"zero" values that the core
// now treats as "auto". Preprocess maps all of them to the documented
// default so existing data parses cleanly — subsequent writes serialize
// the normalized value.
export const VmessSecuritySchema = z.preprocess(
(val) => (val === '' ? 'auto' : val),
(val) => (val === '' || val === 'none' || val === 'zero' ? 'auto' : val),
VmessSecurityEnum,
);
export type VmessSecurity = z.infer<typeof VmessSecurityEnum>;
@@ -5,12 +5,12 @@ import { z } from 'zod';
// plus optional QUIC tuning. The `settings` sub-object is polymorphic on
// `type`; we model the wire-faithful shape with a permissive
// record-of-unknown for `settings` and leave per-type tightening to
// Step 6 — there are 8 UDP mask types plus 3 TCP mask types, each with
// Step 6 — there are 8 UDP mask types plus 4 TCP mask types, each with
// distinct setting fields, and modeling them all as discriminated unions
// here would dwarf the rest of the stream module without buying anything
// the safety net doesn't already cover.
export const TcpMaskTypeSchema = z.enum(['fragment', 'sudoku', 'header-custom']);
export const TcpMaskTypeSchema = z.enum(['fragment', 'sudoku', 'header-custom', 'xmc']);
export type TcpMaskType = z.infer<typeof TcpMaskTypeSchema>;
export const TcpMaskSchema = z.object({
+22 -4
View File
@@ -52,10 +52,28 @@ const TransportNetworkSettingsSchema = z.discriminatedUnion('network', [
// mode. The transportless branch accepts that shape (network absent), while a
// present-but-invalid network still fails both branches so a typo can't slip
// through. `network: never().optional()` reads as "this key must be absent".
export const NetworkSettingsSchema = z.union([
TransportNetworkSettingsSchema,
z.object({ network: z.never().optional() }),
]);
//
// The preprocess folds `method` — xray-core v26.7.11's preferred alias for
// `network`, which wins over `network` when both are present — back into the
// panel-canonical `network` key, so imported/pasted configs keyed on the
// alias don't silently match the transportless branch and lose their
// transport.
export const NetworkSettingsSchema = z.preprocess(
(val) => {
if (val && typeof val === 'object' && 'method' in val) {
const { method, ...rest } = val as Record<string, unknown>;
if (typeof method === 'string' && method !== '') {
return { ...rest, network: method };
}
return rest;
}
return val;
},
z.union([
TransportNetworkSettingsSchema,
z.object({ network: z.never().optional() }),
]),
);
export type NetworkSettings = z.infer<typeof NetworkSettingsSchema>;
// Orthogonal extras that ride alongside the network and security branches.