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
6 changed files with 12 additions and 7 deletions

View File

@@ -55,7 +55,7 @@ type Inbound struct {
// Xray configuration fields
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"`
Settings string `json:"settings" form:"settings"`
StreamSettings string `json:"streamSettings" form:"streamSettings"`

View File

@@ -291,7 +291,7 @@ export const InboundSchema = z.object({
lastTrafficResetTime: z.number().int(),
listen: z.string(),
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']),
remark: z.string(),
settings: z.unknown(),

View File

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

View File

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

View File

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