fix(node): bound the panel GUIDs a peer reports

A peer's panelGuid is copied into nodes.guid and into every inbound row
it reports (an indexed column), a forwarded origin GUID likewise, and a
GUID-keyed IP tree or a master's global-traffic push keys one row per
client. One oversized value therefore multiplied into gigabytes stored.
GUIDs over 64 bytes (panels mint 36-character UUIDs) now fail the
heartbeat, fall back to the reporting node's key, or are dropped.
This commit is contained in:
MHSanaei
2026-10-31 09:22:24 +00:00
parent 9cf8c87e8d
commit 87f3f54ea6
7 changed files with 67 additions and 2 deletions
@@ -2,6 +2,7 @@ package service
import (
"slices"
"strings"
"testing"
"github.com/mhsanaei/3x-ui/v3/internal/database"
@@ -448,3 +449,24 @@ func TestSetRemoteTraffic_DefaultsShareAddressFieldsForNewCentralInbound(t *test
t.Fatalf("new central inbound share fields = (%q, %q), want (node, empty)", ib.ShareAddrStrategy, ib.ShareAddr)
}
}
// An origin GUID is copied into the inbound row and its index; one a node forwards over
// the GUID bound is attributed to the reporting node instead of being stored.
func TestSetRemoteTraffic_RefusesAnOversizedForwardedOrigin(t *testing.T) {
setupConflictDB(t)
db := database.GetDB()
if err := db.Create(&model.Node{Id: 1, Name: "node2", Address: "10.0.0.2", Port: 2053, ApiToken: "t", Guid: "node2-guid"}).Error; err != nil {
t.Fatalf("create node: %v", err)
}
snap := &runtime.TrafficSnapshot{Inbounds: []*model.Inbound{{
Tag: "in-443-tcp", Enable: true, Port: 443, Protocol: model.VLESS, Settings: `{"clients":[]}`,
OriginNodeGuid: strings.Repeat("g", maxPanelGuidLen+1),
}}}
if _, err := (&InboundService{}).setRemoteTrafficLocked(1, snap, false, false); err != nil {
t.Fatalf("setRemoteTrafficLocked: %v", err)
}
var ib model.Inbound
if err := db.Where("tag = ?", "in-443-tcp").First(&ib).Error; err != nil || ib.OriginNodeGuid != "node2-guid" {
t.Fatalf("origin = %d bytes (%v), want the reporting node's GUID", len(ib.OriginNodeGuid), err)
}
}