diff --git a/frontend/src/lib/xray/node-protocols.ts b/frontend/src/lib/xray/node-protocols.ts index a7adbc8..c068397 100644 --- a/frontend/src/lib/xray/node-protocols.ts +++ b/frontend/src/lib/xray/node-protocols.ts @@ -2,7 +2,10 @@ import { Protocols } from '@/schemas/primitives'; /* * Protocols whose inbounds can live on a sub-node (the "Deploy To" set). - * Everything else (http, mixed, tunnel, tun, mtproto) is panel-local only. + * Everything else (http, tunnel, tun, mtproto) is panel-local only. Mixed + * is eligible: it is a plain xray inbound, and node-local mixed inbounds + * already sync back to the panel — hiding the picker only blocked creating + * them from the master. * Shared by the inbound form's Deploy To selector and the clone dialog's * target picker so the two surfaces can never drift apart. */ @@ -13,4 +16,5 @@ export const NODE_ELIGIBLE_PROTOCOLS: Readonly> = { [Protocols.SHADOWSOCKS]: true, [Protocols.HYSTERIA]: true, [Protocols.WIREGUARD]: true, + [Protocols.MIXED]: true, }; diff --git a/internal/web/service/inbound_protocol.go b/internal/web/service/inbound_protocol.go index db7b1fa..5c8c056 100644 --- a/internal/web/service/inbound_protocol.go +++ b/internal/web/service/inbound_protocol.go @@ -57,6 +57,8 @@ func inboundCanEnableTlsFlow(protocol, streamSettings, settings string) bool { // sidecar-managed protocols are absent because their reconcile loops only query // NodeID IS NULL rows, so a node-assigned one would never be reconciled at all. // A new protocol defaults to ineligible until added here, as on the frontend. +// Mixed is a plain xray inbound (not sidecar-managed): node-local mixed +// inbounds already sync back and are managed by the panel, so it is eligible. var nodeEligibleProtocols = map[model.Protocol]bool{ model.VLESS: true, model.VMESS: true, @@ -64,6 +66,7 @@ var nodeEligibleProtocols = map[model.Protocol]bool{ model.Shadowsocks: true, model.Hysteria: true, model.WireGuard: true, + model.Mixed: true, } // isNodeEligibleProtocol reports whether protocol may be assigned to a node. diff --git a/internal/web/service/inbound_protocol_test.go b/internal/web/service/inbound_protocol_test.go index 3893f9d..af43e22 100644 --- a/internal/web/service/inbound_protocol_test.go +++ b/internal/web/service/inbound_protocol_test.go @@ -93,13 +93,13 @@ func TestInboundCanHostFallbacks_StaysTcpOnly(t *testing.T) { // frontend/src/pages/inbounds/form/InboundFormModal.tsx -- keep both lists // in sync if a protocol's node-eligibility ever changes. func TestIsNodeEligibleProtocol(t *testing.T) { - eligible := []model.Protocol{model.VLESS, model.VMESS, model.Trojan, model.Shadowsocks, model.Hysteria, model.WireGuard} + eligible := []model.Protocol{model.VLESS, model.VMESS, model.Trojan, model.Shadowsocks, model.Hysteria, model.WireGuard, model.Mixed} for _, p := range eligible { if !isNodeEligibleProtocol(p) { t.Errorf("isNodeEligibleProtocol(%q) = false, want true", p) } } - ineligible := []model.Protocol{model.MTProto, model.AmneziaWG, model.Mixed, model.HTTP, model.Tunnel} + ineligible := []model.Protocol{model.MTProto, model.AmneziaWG, model.HTTP, model.Tunnel} for _, p := range ineligible { if isNodeEligibleProtocol(p) { t.Errorf("isNodeEligibleProtocol(%q) = true, want false", p)