diff --git a/frontend/src/hooks/useXraySetting.ts b/frontend/src/hooks/useXraySetting.ts index e137a928c..71f9a40cc 100644 --- a/frontend/src/hooks/useXraySetting.ts +++ b/frontend/src/hooks/useXraySetting.ts @@ -26,20 +26,24 @@ function normalizeOutboundTestUrl(url: string) { return url || DEFAULT_TEST_URL; } +// The core lowercases a protocol id and a transport name before resolving +// either, so "WireGuard"/"KCP" still build a UDP handler a TCP dial misreports. export function isUdpOutbound(outbound: unknown): boolean { const o = outbound as - | { protocol?: string; streamSettings?: { network?: string } } + | { protocol?: unknown; streamSettings?: { network?: unknown } } | null | undefined; - const p = o?.protocol; - const n = o?.streamSettings?.network; + const rawNetwork = o?.streamSettings?.network; + const network = typeof rawNetwork === 'string' ? rawNetwork.toLowerCase() : ''; return ( - p === 'wireguard' || - p === 'hysteria' || - p === 'amneziawg' || - n === 'hysteria' || - n === 'kcp' || - n === 'quic' + isOutboundProtocol(o, 'wireguard') || + isOutboundProtocol(o, 'hysteria') || + isOutboundProtocol(o, 'amneziawg') || + network === 'hysteria' || + network === 'kcp' || + // The core resolves "kcp" and "mkcp" to the same mKCP transport. + network === 'mkcp' || + network === 'quic' ); } diff --git a/frontend/src/pages/inbounds/form/protocols/mtproto.tsx b/frontend/src/pages/inbounds/form/protocols/mtproto.tsx index 47046c3b7..12ca391e0 100644 --- a/frontend/src/pages/inbounds/form/protocols/mtproto.tsx +++ b/frontend/src/pages/inbounds/form/protocols/mtproto.tsx @@ -11,7 +11,7 @@ export default function MtprotoFields() { const routeThroughXray = useWatch({ control, name: 'settings.routeThroughXray' }) as | boolean | undefined; - const { data: outboundTags } = useOutboundTags(); + const { data: outboundTags } = useOutboundTags({ excludeBlackhole: true }); return ( <>