mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-08 13:24:33 +00:00
feat(inbounds): support Unix domain socket path in Listen field (#4429)
UDS listen already worked for proxying (the listen string is passed to xray verbatim and port 0 is accepted), and the Go sub/link layer already ignores the bind listen. The only gap was the frontend resolveAddr, which would put a socket-path listen into share/sub links (e.g. vless://uuid@/run/xray/x.sock:0). resolveAddr now treats a path-style listen (starting with / or @) as having no client-reachable address and falls back to hostOverride/hostname. Adds a test and a Listen-field help hint across all locales.
This commit is contained in:
@@ -706,15 +706,22 @@ export function genWireguardConfig(input: GenWireguardLinkInput): string {
|
||||
|
||||
export type { WireguardInboundPeer };
|
||||
|
||||
function isUnixSocketListen(listen: string): boolean {
|
||||
return listen.startsWith('/') || listen.startsWith('@');
|
||||
}
|
||||
|
||||
// Orchestrators.
|
||||
// resolveAddr picks the host that goes into share/sub links. Order:
|
||||
// 1. hostOverride (caller supplies node address for node-managed inbounds)
|
||||
// 2. inbound's bind listen (when explicit, not 0.0.0.0)
|
||||
// 2. inbound's bind listen (when it's an explicit reachable address —
|
||||
// not 0.0.0.0 and not a unix domain socket path)
|
||||
// 3. fallbackHostname (caller-supplied — typically window.location.hostname
|
||||
// in the browser; tests pass a fixed value)
|
||||
export function resolveAddr(inbound: Inbound, hostOverride: string, fallbackHostname: string): string {
|
||||
if (hostOverride.length > 0) return hostOverride;
|
||||
if (inbound.listen.length > 0 && inbound.listen !== '0.0.0.0') return inbound.listen;
|
||||
if (inbound.listen.length > 0 && inbound.listen !== '0.0.0.0' && !isUnixSocketListen(inbound.listen)) {
|
||||
return inbound.listen;
|
||||
}
|
||||
return fallbackHostname;
|
||||
}
|
||||
|
||||
|
||||
@@ -481,7 +481,11 @@ export default function InboundFormModal({
|
||||
<Select disabled={mode === 'edit'} options={PROTOCOL_OPTIONS} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="listen" label={t('pages.inbounds.address')}>
|
||||
<Form.Item
|
||||
name="listen"
|
||||
label={t('pages.inbounds.address')}
|
||||
extra={t('pages.inbounds.form.listenHelp')}
|
||||
>
|
||||
<Input placeholder={t('pages.inbounds.monitorDesc')} />
|
||||
</Form.Item>
|
||||
|
||||
|
||||
@@ -196,6 +196,19 @@ describe('resolveAddr precedence', () => {
|
||||
)).toBe('fallback.test');
|
||||
});
|
||||
|
||||
it('skips a unix socket path listen and falls through to fallbackHostname', () => {
|
||||
expect(resolveAddr(
|
||||
{ ...baseInbound, listen: '/run/xray/in.sock' } as never,
|
||||
'',
|
||||
'fallback.test',
|
||||
)).toBe('fallback.test');
|
||||
expect(resolveAddr(
|
||||
{ ...baseInbound, listen: '@xray-abstract' } as never,
|
||||
'',
|
||||
'fallback.test',
|
||||
)).toBe('fallback.test');
|
||||
});
|
||||
|
||||
it('falls through to fallbackHostname when listen is empty', () => {
|
||||
expect(resolveAddr(
|
||||
baseInbound as never,
|
||||
|
||||
Reference in New Issue
Block a user