feat(nodes): per-node client IP attribution for IP-limit

Record each panel's own Xray IP observations under its panelGuid and merge each node's guid-keyed report on the master, so the panel can tell which node a client IP is connecting through (the flat inbound_client_ips union is pushed back to every node and cannot attribute). Adds the NodeClientIp model + migration, the clientIpsByGuid endpoint and node-sync merge, node-name labels in the client IP log, and cleanup on node deletion.
This commit is contained in:
MHSanaei
2026-06-15 23:50:05 +02:00
parent d882d6aa74
commit 9385b6c609
13 changed files with 598 additions and 45 deletions
+12
View File
@@ -433,12 +433,24 @@ func FilterNodeSnapshot(n *model.Node, snap *runtime.TrafficSnapshot) {
func (s *NodeService) Delete(id int) error {
db := database.GetDB()
// Capture the node's guid before deleting the row so we can drop its per-node
// IP attribution (NodeClientIp is keyed by guid, not node id).
var guid string
var n model.Node
if err := db.Select("guid").Where("id = ?", id).First(&n).Error; err == nil {
guid = n.Guid
}
if err := db.Where("id = ?", id).Delete(model.Node{}).Error; err != nil {
return err
}
if err := db.Where("node_id = ?", id).Delete(&model.NodeClientTraffic{}).Error; err != nil {
return err
}
if guid != "" {
if err := db.Where("node_guid = ?", guid).Delete(&model.NodeClientIp{}).Error; err != nil {
return err
}
}
if mgr := runtime.GetManager(); mgr != nil {
mgr.InvalidateNode(id)
}