mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-11 07:06:06 +00:00
fix(inbounds): drop listen address from auto-generated inbound tag
A non-empty, non-any Address (listen) leaked into the tag as in-<listen>:<port>-<transport> (e.g. in-127.0.0.1:443-tcp). The tag is now always in-<port>-<transport>, with the node prefix and numeric dedup suffix still handling uniqueness across nodes and same-port/different-listen inbounds. Mirrored in the Go authority and the TS form preview, kept in parity by tests. Existing colon-form tags are now treated as custom, so editing such an inbound preserves its tag rather than rewriting it; new inbounds (or a cleared tag field) get the clean form.
This commit is contained in:
@@ -49,12 +49,8 @@ function transportTagSuffix(bits: TransportBits): string {
|
||||
return 'any';
|
||||
}
|
||||
|
||||
function isAnyListen(listen: string): boolean {
|
||||
return listen === '' || listen === '0.0.0.0' || listen === '::' || listen === '::0';
|
||||
}
|
||||
|
||||
function baseInboundTag(listen: string, port: number): string {
|
||||
return isAnyListen(listen) ? `in-${port}` : `in-${listen}:${port}`;
|
||||
function baseInboundTag(port: number): string {
|
||||
return `in-${port}`;
|
||||
}
|
||||
|
||||
function nodeTagPrefix(nodeId: number | null | undefined): string {
|
||||
@@ -62,7 +58,6 @@ function nodeTagPrefix(nodeId: number | null | undefined): string {
|
||||
}
|
||||
|
||||
export interface InboundTagInput {
|
||||
listen: string;
|
||||
port: number;
|
||||
nodeId: number | null | undefined;
|
||||
protocol: string;
|
||||
@@ -74,7 +69,7 @@ export function composeInboundTag(input: InboundTagInput): string {
|
||||
const bits = inboundTransports(input.protocol, input.streamSettings, input.settings);
|
||||
return (
|
||||
nodeTagPrefix(input.nodeId)
|
||||
+ baseInboundTag(input.listen ?? '', input.port ?? 0)
|
||||
+ baseInboundTag(input.port ?? 0)
|
||||
+ '-'
|
||||
+ transportTagSuffix(bits)
|
||||
);
|
||||
|
||||
@@ -160,7 +160,6 @@ export default function InboundFormModal({
|
||||
const security = Form.useWatch(['streamSettings', 'security'], form) ?? 'none';
|
||||
const streamEnabled = canEnableStream({ protocol });
|
||||
|
||||
const wListen = Form.useWatch('listen', form) ?? '';
|
||||
const wPort = Form.useWatch('port', form);
|
||||
const wNodeId = Form.useWatch('nodeId', form) ?? null;
|
||||
const wTag = Form.useWatch('tag', form) ?? '';
|
||||
@@ -169,7 +168,6 @@ export default function InboundFormModal({
|
||||
const autoTagRef = useRef(true);
|
||||
const lastWrittenTagRef = useRef('');
|
||||
const currentTagInput = (): InboundTagInput => ({
|
||||
listen: typeof wListen === 'string' ? wListen : '',
|
||||
port: typeof wPort === 'number' ? wPort : 0,
|
||||
nodeId: typeof wNodeId === 'number' ? wNodeId : null,
|
||||
protocol,
|
||||
@@ -293,7 +291,6 @@ export default function InboundFormModal({
|
||||
form.setFieldsValue(initial);
|
||||
const initialTag = (initial.tag ?? '') as string;
|
||||
autoTagRef.current = isAutoInboundTag(initialTag, {
|
||||
listen: initial.listen ?? '',
|
||||
port: initial.port ?? 0,
|
||||
nodeId: initial.nodeId ?? null,
|
||||
protocol: initial.protocol,
|
||||
@@ -329,7 +326,7 @@ export default function InboundFormModal({
|
||||
form.setFieldValue('tag', next);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [open, wListen, wPort, wNodeId, protocol, network, mixedUdpOn, wSsNetwork, wTunnelNetwork]);
|
||||
}, [open, wPort, wNodeId, protocol, network, mixedUdpOn, wSsNetwork, wTunnelNetwork]);
|
||||
|
||||
// Why: protocol picker reset cascades through the form — clearing the
|
||||
// settings DU branch and dropping a nodeId that no longer applies. The
|
||||
|
||||
@@ -7,7 +7,6 @@ import { composeInboundTag, isAutoInboundTag, type InboundTagInput } from '@/lib
|
||||
// tag the backend re-derives on save.
|
||||
describe('composeInboundTag transport suffix parity', () => {
|
||||
const base = (over: Partial<InboundTagInput>): InboundTagInput => ({
|
||||
listen: '0.0.0.0',
|
||||
port: 443,
|
||||
nodeId: null,
|
||||
protocol: 'vless',
|
||||
@@ -36,9 +35,9 @@ describe('composeInboundTag transport suffix parity', () => {
|
||||
expect(composeInboundTag(input)).toBe(want);
|
||||
});
|
||||
|
||||
it('scopes a non-any listen and node prefix', () => {
|
||||
expect(composeInboundTag(base({ listen: '127.0.0.1', port: 8443, streamSettings: { network: 'tcp' } })))
|
||||
.toBe('in-127.0.0.1:8443-tcp');
|
||||
it('ignores the listen address and adds the node prefix', () => {
|
||||
expect(composeInboundTag(base({ port: 8443, streamSettings: { network: 'tcp' } })))
|
||||
.toBe('in-8443-tcp');
|
||||
expect(composeInboundTag(base({ nodeId: 1, port: 443, streamSettings: { network: 'tcp' } })))
|
||||
.toBe('n1-in-443-tcp');
|
||||
});
|
||||
@@ -47,7 +46,7 @@ describe('composeInboundTag transport suffix parity', () => {
|
||||
// Parity with TestIsAutoGeneratedTag.
|
||||
describe('isAutoInboundTag', () => {
|
||||
const input: InboundTagInput = {
|
||||
listen: '0.0.0.0', port: 443, nodeId: null, protocol: 'vless', streamSettings: { network: 'tcp' },
|
||||
port: 443, nodeId: null, protocol: 'vless', streamSettings: { network: 'tcp' },
|
||||
};
|
||||
|
||||
it('recognises canonical, dedup-suffixed and empty as auto', () => {
|
||||
|
||||
Reference in New Issue
Block a user