From 6ed5def90ab31ce966f873bd17bcf0be11dc39aa Mon Sep 17 00:00:00 2001 From: younesvatan78 Date: Thu, 4 Jun 2026 19:46:35 +0330 Subject: [PATCH] fix(node-traffic): restart remote xray after disabling clients to kill active sessions When a client's traffic limit is reached on a remote node, the panel pushes enable=false to that node via UpdateInbound. The node calls RemoveUser on its local xray, which blocks new connections but leaves any already-established TCP session alive. The user could continue browsing/downloading until they disconnected voluntarily. Fix: after successfully pushing a client disable to a remote node, call RestartXray on that node. This mirrors what already happens for the local node when the "Restart Xray on client disable" setting is enabled (default: on), and ensures active sessions are terminated immediately on all nodes where the client was disabled. Co-Authored-By: Claude Sonnet 4.6 --- web/service/inbound.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/web/service/inbound.go b/web/service/inbound.go index 1358b3fb..85697a14 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -2247,6 +2247,9 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error) } } + // Track which remote nodes had clients successfully disabled so we can + // restart their xray and kill the existing active connections. + disabledNodeIDs := make(map[int]struct{}) for inboundID, group := range remoteByInbound { emails := make(map[string]struct{}, len(group)) for _, t := range group { @@ -2255,6 +2258,31 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error) if pushErr := s.disableRemoteClients(tx, inboundID, emails); pushErr != nil { logger.Warning("disableInvalidClients: push to remote failed for inbound", inboundID, ":", pushErr) needRestart = true + } else { + for _, t := range group { + if t.NodeID != nil { + disabledNodeIDs[*t.NodeID] = struct{}{} + } + } + } + } + + // Restart xray on each affected remote node so active connections are + // dropped immediately, not just blocked on the next reconnect attempt. + if len(disabledNodeIDs) > 0 { + restartOnDisable, _ := (&SettingService{}).GetRestartXrayOnClientDisable() + if restartOnDisable { + for nodeID := range disabledNodeIDs { + nodeIDCopy := nodeID + rt, rtErr := runtime.GetManager().RuntimeFor(&nodeIDCopy) + if rtErr != nil { + logger.Warning("disableInvalidClients: get runtime for node", nodeID, "failed:", rtErr) + continue + } + if rtErr = rt.RestartXray(context.Background()); rtErr != nil { + logger.Warning("disableInvalidClients: restart xray on node", nodeID, "failed:", rtErr) + } + } } }