fix(inbounds): allow port 0 for UDS inbounds (#4783)

Unix Domain Socket inbounds (listen path starting with /) use port 0, which xray-core ignores. Validation was hard-locked to a minimum of 1 in three places: the shared Zod PortSchema, the AntD InputNumber, and the Go Inbound model tag. Adds an InboundPortSchema (min 0) for the inbound form/API schemas, makes the port InputNumber min UDS-aware, and relaxes the Inbound model validate tag to gte=0. PortSchema and the Node model stay min 1.
This commit is contained in:
MHSanaei 2026-06-01 23:26:20 +02:00
parent 3657ed55dc
commit ccd0853b6c
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
6 changed files with 12 additions and 7 deletions

View file

@ -55,7 +55,7 @@ type Inbound struct {
// Xray configuration fields // Xray configuration fields
Listen string `json:"listen" form:"listen"` Listen string `json:"listen" form:"listen"`
Port int `json:"port" form:"port" validate:"gte=1,lte=65535"` Port int `json:"port" form:"port" validate:"gte=0,lte=65535"`
Protocol Protocol `json:"protocol" form:"protocol" validate:"required,oneof=vmess vless trojan shadowsocks wireguard hysteria http mixed tunnel tun"` Protocol Protocol `json:"protocol" form:"protocol" validate:"required,oneof=vmess vless trojan shadowsocks wireguard hysteria http mixed tunnel tun"`
Settings string `json:"settings" form:"settings"` Settings string `json:"settings" form:"settings"`
StreamSettings string `json:"streamSettings" form:"streamSettings"` StreamSettings string `json:"streamSettings" form:"streamSettings"`

View file

@ -291,7 +291,7 @@ export const InboundSchema = z.object({
lastTrafficResetTime: z.number().int(), lastTrafficResetTime: z.number().int(),
listen: z.string(), listen: z.string(),
nodeId: z.number().int().nullable().optional(), nodeId: z.number().int().nullable().optional(),
port: z.number().int().min(1).max(65535), port: z.number().int().min(0).max(65535),
protocol: z.enum(['vmess', 'vless', 'trojan', 'shadowsocks', 'wireguard', 'hysteria', 'http', 'mixed', 'tunnel', 'tun']), protocol: z.enum(['vmess', 'vless', 'trojan', 'shadowsocks', 'wireguard', 'hysteria', 'http', 'mixed', 'tunnel', 'tun']),
remark: z.string(), remark: z.string(),
settings: z.unknown(), settings: z.unknown(),

View file

@ -161,6 +161,8 @@ export default function InboundFormModal({
const streamEnabled = canEnableStream({ protocol }); const streamEnabled = canEnableStream({ protocol });
const wPort = Form.useWatch('port', form); const wPort = Form.useWatch('port', form);
const wListen = (Form.useWatch('listen', form) ?? '') as string;
const isUdsListen = wListen.startsWith('/');
const wNodeId = Form.useWatch('nodeId', form) ?? null; const wNodeId = Form.useWatch('nodeId', form) ?? null;
const wTag = Form.useWatch('tag', form) ?? ''; const wTag = Form.useWatch('tag', form) ?? '';
const wSsNetwork = Form.useWatch(['settings', 'network'], form); const wSsNetwork = Form.useWatch(['settings', 'network'], form);
@ -488,7 +490,7 @@ export default function InboundFormModal({
label={t('pages.inbounds.port')} label={t('pages.inbounds.port')}
rules={[antdRule(InboundFormBaseSchema.shape.port, t)]} rules={[antdRule(InboundFormBaseSchema.shape.port, t)]}
> >
<InputNumber min={1} max={65535} /> <InputNumber min={isUdsListen ? 0 : 1} max={65535} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item

View file

@ -1,6 +1,6 @@
import { z } from 'zod'; import { z } from 'zod';
import { PortSchema, SniffingSchema } from '@/schemas/primitives'; import { InboundPortSchema, SniffingSchema } from '@/schemas/primitives';
import { InboundSettingsSchema } from '@/schemas/protocols/inbound'; import { InboundSettingsSchema } from '@/schemas/protocols/inbound';
import { SecuritySettingsSchema } from '@/schemas/protocols/security'; import { SecuritySettingsSchema } from '@/schemas/protocols/security';
import { NetworkSettingsSchema, StreamExtrasSchema } from '@/schemas/protocols/stream'; import { NetworkSettingsSchema, StreamExtrasSchema } from '@/schemas/protocols/stream';
@ -32,7 +32,7 @@ export const InboundCoreSchema = z.object({
enable: z.boolean().default(true), enable: z.boolean().default(true),
expiryTime: z.number().int().default(0), expiryTime: z.number().int().default(0),
listen: z.string().default(''), listen: z.string().default(''),
port: PortSchema, port: InboundPortSchema,
tag: z.string().default(''), tag: z.string().default(''),
sniffing: SniffingSchema.default({ sniffing: SniffingSchema.default({
enabled: false, enabled: false,

View file

@ -1,6 +1,6 @@
import { z } from 'zod'; import { z } from 'zod';
import { PortSchema, SniffingSchema } from '@/schemas/primitives'; import { InboundPortSchema, SniffingSchema } from '@/schemas/primitives';
import { InboundSettingsSchema } from '@/schemas/protocols/inbound'; import { InboundSettingsSchema } from '@/schemas/protocols/inbound';
import { SecuritySettingsSchema } from '@/schemas/protocols/security'; import { SecuritySettingsSchema } from '@/schemas/protocols/security';
import { NetworkSettingsSchema, StreamExtrasSchema } from '@/schemas/protocols/stream'; import { NetworkSettingsSchema, StreamExtrasSchema } from '@/schemas/protocols/stream';
@ -44,7 +44,7 @@ export type InboundDbFields = z.infer<typeof InboundDbFieldsSchema>;
export const InboundFormBaseSchema = z.object({ export const InboundFormBaseSchema = z.object({
remark: z.string().default(''), remark: z.string().default(''),
enable: z.boolean().default(true), enable: z.boolean().default(true),
port: PortSchema, port: InboundPortSchema,
listen: z.string().default(''), listen: z.string().default(''),
tag: z.string().default(''), tag: z.string().default(''),
expiryTime: z.number().int().default(0), expiryTime: z.number().int().default(0),

View file

@ -2,3 +2,6 @@ import { z } from 'zod';
export const PortSchema = z.number().int().min(1).max(65535); export const PortSchema = z.number().int().min(1).max(65535);
export type Port = z.infer<typeof PortSchema>; export type Port = z.infer<typeof PortSchema>;
export const InboundPortSchema = z.number().int().min(0).max(65535);
export type InboundPort = z.infer<typeof InboundPortSchema>;