feat(inbounds): deploy AmneziaWG, TUIC and MTProto inbounds to nodes

The node gate assumed a node-assigned sidecar row would never converge,
because the master's reconcile loops only read node_id IS NULL rows. But
a pushed row is local on the node's own panel, whose AmneziaWG, TUIC and
mtg loops run it like any other; node-adopted rows of these protocols
already worked. Only creating or cloning them from the master was blocked.

Open the three protocols on both lists and fix what assumed the master's
host for a node row:
- A node older than the release that introduced the protocol (MTProto
  v3.5.0, AmneziaWG v3.7.0, TUIC v3.8.0) would hand it to Xray as-is, so
  add and protocol-changing update refuse it, and a node that has not
  reported its version yet. Dev builds ("dev+<sha>") track main and pass.
- MTProto's routeXrayPort is a loopback port on the host running mtg.
  The master no longer allocates one, nor forwards a cloned source's, for
  a node row; the node allocates its own and node sync adopts it back.
- AmneziaWG forwardedPorts were checked against the master's inbounds,
  web port and id-derived relay ports. A node row is now checked against
  its own node's inbounds; the node re-checks what only it knows.
  UpdateInbound restores the stored nodeId before that check.

Verified on a docker master+node pair: AWG, routed MTProto and TUIC
created and cloned from the master start on the node (interface, mtg,
tuic-server); an AWG client added and an MTProto client edited on the
master apply on the node; the node-chosen egress port survives edits.

Closes #6306
This commit is contained in:
MHSanaei
2026-10-03 00:26:46 +02:00
parent 9b957b969b
commit ed31ee432c
12 changed files with 387 additions and 75 deletions
+5 -1
View File
@@ -2,7 +2,8 @@ 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, mixed, tunnel, tun) is panel-local only. The sidecar
* protocols run on the node's own panel; the backend refuses a node too old.
* 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 +14,7 @@ export const NODE_ELIGIBLE_PROTOCOLS: Readonly<Record<string, true>> = {
[Protocols.SHADOWSOCKS]: true,
[Protocols.HYSTERIA]: true,
[Protocols.WIREGUARD]: true,
[Protocols.MTPROTO]: true,
[Protocols.AMNEZIAWG]: true,
[Protocols.TUIC]: true,
};