mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-22 20:46:08 +00:00
feat(tls,reality): port xray TLS/REALITY fields, cert-hash helpers, fallback UX
TLS: add verifyPeerCertByName (vcn) to inbound settings + emit in both share-link generators (frontend + Go sub) and outbound parser; the allowInsecure replacement xray removed after 2026-06-01. Add server-side curvePreferences, masterKeyLog, echSockopt (passthrough + form) at tlsSettings top-level so they survive the panel-only settings strip. REALITY: add limitFallbackUpload/Download (afterBytes/bytesPerSec/burstBytesPerSec) with per-field tooltips, plus masterKeyLog. Verified field names/semantics against pinned xray v1.260327.1 (bytesPerSec=0 disables). Hosts: fix verify_peer_cert_by_name column bool->string (xray expects comma-separated names) with an idempotent, history-gate-free migration (SQLite typeof blank; Postgres ALTER once); emit vcn for hosts/external proxies. Server: add getCertHash (local cert DER SHA-256) and getRemoteCertHash (xray tls ping) endpoints + api-docs; wire pinned-cert field buttons. Drop the meaningless random-hash button. Xray UI: metrics endpoint (listen/tag) config in Basics; import/export for routing rules and outbounds. Fallbacks card: compact empty state, header-aligned actions, responsive labeled grid rows. i18n: add all new keys to every locale; drop unused generateRandomPin.
This commit is contained in:
@@ -14,6 +14,17 @@ export const RealityClientSettingsSchema = z.object({
|
||||
});
|
||||
export type RealityClientSettings = z.infer<typeof RealityClientSettingsSchema>;
|
||||
|
||||
// REALITY fallback rate-limit (xray-core reality.LimitFallback): throttles the
|
||||
// fallback stream after `afterBytes`, then caps it at `bytesPerSec` with an
|
||||
// optional `burstBytesPerSec`. Optional so existing inbounds round-trip
|
||||
// unchanged — the object is only emitted once a user sets a non-zero value.
|
||||
export const RealityLimitFallbackSchema = z.object({
|
||||
afterBytes: z.number().int().min(0).default(0),
|
||||
bytesPerSec: z.number().int().min(0).default(0),
|
||||
burstBytesPerSec: z.number().int().min(0).default(0),
|
||||
});
|
||||
export type RealityLimitFallback = z.infer<typeof RealityLimitFallbackSchema>;
|
||||
|
||||
// xray-core accepts both `target` and `dest` as the REALITY destination —
|
||||
// they are aliases (infra/conf/transport_internet.go: REALITYConfig has
|
||||
// `json:"target"` and `json:"dest"`). The panel writes `target`, but configs
|
||||
@@ -52,6 +63,11 @@ export const RealityStreamSettingsSchema = z.preprocess(
|
||||
maxTimediff: z.number().int().min(0).default(0),
|
||||
shortIds: z.array(z.string()).default([]),
|
||||
mldsa65Seed: z.string().default(''),
|
||||
// Server-side TLS master-key log path (xray-core reality.Config). Optional
|
||||
// so existing inbounds round-trip unchanged.
|
||||
masterKeyLog: z.string().optional(),
|
||||
limitFallbackUpload: RealityLimitFallbackSchema.optional(),
|
||||
limitFallbackDownload: RealityLimitFallbackSchema.optional(),
|
||||
settings: RealityClientSettingsSchema.default({
|
||||
publicKey: '',
|
||||
fingerprint: 'chrome',
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { SockoptStreamSettingsSchema } from '@/schemas/protocols/stream/sockopt';
|
||||
|
||||
export const TlsVersionSchema = z.enum(['1.0', '1.1', '1.2', '1.3']);
|
||||
export type TlsVersion = z.infer<typeof TlsVersionSchema>;
|
||||
|
||||
@@ -57,6 +59,11 @@ export const TlsClientSettingsSchema = z.object({
|
||||
fingerprint: TlsFingerprintSchema.default('chrome'),
|
||||
echConfigList: z.string().default(''),
|
||||
pinnedPeerCertSha256: z.array(z.string()).default([]),
|
||||
// Panel-only client directive (v2rayN `vcn`): verify the server certificate
|
||||
// against this name instead of the SNI. Comma-separated names. Shipped in
|
||||
// share links / subscriptions; the modern replacement for `allowInsecure`,
|
||||
// which xray-core removed after 2026-06-01.
|
||||
verifyPeerCertByName: z.string().default(''),
|
||||
});
|
||||
export type TlsClientSettings = z.infer<typeof TlsClientSettingsSchema>;
|
||||
|
||||
@@ -73,6 +80,12 @@ export const TlsStreamSettingsSchema = z.object({
|
||||
certificates: z.array(TlsCertSchema).default([]),
|
||||
alpn: z.array(AlpnSchema).default(['h2', 'http/1.1']),
|
||||
echServerKeys: z.string().default(''),
|
||||
settings: TlsClientSettingsSchema.default({ fingerprint: 'chrome', echConfigList: '', pinnedPeerCertSha256: [] }),
|
||||
// Server-side TLS fields (xray-core TLSConfig top-level): survive the
|
||||
// panel-only `settings` strip and reach the runtime config. Optional so
|
||||
// existing inbounds round-trip unchanged.
|
||||
curvePreferences: z.array(z.string()).optional(),
|
||||
masterKeyLog: z.string().optional(),
|
||||
echSockopt: SockoptStreamSettingsSchema.optional(),
|
||||
settings: TlsClientSettingsSchema.default({ fingerprint: 'chrome', echConfigList: '', pinnedPeerCertSha256: [], verifyPeerCertByName: '' }),
|
||||
});
|
||||
export type TlsStreamSettings = z.infer<typeof TlsStreamSettingsSchema>;
|
||||
|
||||
@@ -23,6 +23,7 @@ export const ExternalProxyEntrySchema = z.object({
|
||||
),
|
||||
alpn: z.array(AlpnSchema).optional(),
|
||||
pinnedPeerCertSha256: z.array(z.string()).optional(),
|
||||
verifyPeerCertByName: z.string().optional(),
|
||||
echConfigList: z.string().optional(),
|
||||
});
|
||||
export type ExternalProxyEntry = z.infer<typeof ExternalProxyEntrySchema>;
|
||||
|
||||
Reference in New Issue
Block a user