feat(panel): build-before-bind + socks5 fixed node account (items 20+21)

Item 20: drop the zero-client deploy gate in ValidateNodeDeploy for
all protocols, stop RebuildNode from auto-removing a node whose
bindings reach zero, and let server/heartbeat reconciliation rebuild
zero-client nodes like any other. Nodes are built and deployed first;
bindings can be added and removed freely.

Item 21: socks5-auth nodes carry one node-level fixed account
(node.socksUser/socksPassword, minted at creation or by the store-load
migration MigrateSocksNodeCredentials, idempotent). The sing-box
inbound's only user is that pair regardless of bindings; subscription
links for every bound customer carry the same pair. The generated
username avoids the ng: prefix so the agent never attributes the
account's traffic to a customer — it stays on the node's inbound
counters. Edit form shows both fields (copyable) for socks nodes;
NormalizeNode validates operator-supplied usernames.
This commit is contained in:
aaaamoooo
2026-10-21 10:40:58 +00:00
parent bb974e2ed7
commit 2fafd85d1f
9 changed files with 297 additions and 34 deletions
+7 -1
View File
@@ -30,7 +30,13 @@ func goldenSubData() *Data {
Topology: "direct", NetworkMode: "ipv4", Port: 23461, Status: "active",
WSPath: StrPtr("/wspath123"), Artifacts: map[string]json.RawMessage{}},
{ID: "nod_sk", Name: "Socks", ServerID: "srv_entry", Protocol: "socks5-auth",
Topology: "direct", NetworkMode: "ipv4", Port: 23462, Status: "active", Artifacts: map[string]json.RawMessage{}},
Topology: "direct", NetworkMode: "ipv4", Port: 23462, Status: "active", Artifacts: map[string]json.RawMessage{},
// Round-3 item 21: the pair lives on the node now. The values
// deliberately equal the old per-binding derivation
// (ng:cus_1 + the customer's relay password) so every format
// body stays byte-identical — the change is only in where
// the pair comes from.
SocksUser: "ng:cus_1", SocksPassword: "FRYXGBkaGxwdHh8gISIjJA=="},
{ID: "nod_rv", Name: "RV-Plain", ServerID: "srv_v6", Protocol: "vless-reality",
Topology: "direct", NetworkMode: "ipv4", Port: 23463, Status: "active",
Reality: &RealityConfig{KeyID: "reality-nod_rv", ServerName: "www.apple.com", DestPort: 443},