浏览代码

fix(xray): force full restart for inbounds with a VLESS reverse client

Hot-applying an inbound change swaps it via DelInbound+AddInbound on
the running core. That unregisters any client's reverse.tag handler
on the xray-core side without closing the bridge's already-established
connection, so the reverse tunnel is silently orphaned until someone
manually restarts xray. diffInbounds now bails out of the hot-apply
path whenever the old or new inbound carries a reverse-tagged client,
falling back to a full restart, which actually drops the socket and
lets the bridge redial on its own.

Also scope the .claude ignore rule to its contents (.claude/*) instead
of the whole directory, so individual files under .claude/ can be
tracked selectively.
MHSanaei 19 小时之前
父节点
当前提交
49773c18de
共有 2 个文件被更改,包括 30 次插入1 次删除
  1. 1 1
      .gitignore
  2. 29 0
      internal/xray/hot_diff.go

+ 1 - 1
.gitignore

@@ -2,7 +2,7 @@
 .idea/
 .vscode/
 .cursor/
-.claude/
+.claude/*
 .cache/
 .sync*
 

+ 29 - 0
internal/xray/hot_diff.go

@@ -108,6 +108,10 @@ func diffInbounds(oldCfg, newCfg *Config, diff *HotDiff) bool {
 		if oldIb.Tag == apiTag || oldIb.Tag == "api" {
 			return false
 		}
+		if exists && (inboundHasReverseClient(oldIb) || inboundHasReverseClient(newIb)) {
+			logger.Debug("hot diff: inbound [", oldIb.Tag, "] carries a reverse-tagged client, forcing a full restart instead of a hot swap")
+			return false
+		}
 		diff.RemovedInboundTags = append(diff.RemovedInboundTags, oldIb.Tag)
 		if exists {
 			raw, err := json.Marshal(newIb)
@@ -134,6 +138,31 @@ func diffInbounds(oldCfg, newCfg *Config, diff *HotDiff) bool {
 	return true
 }
 
+func inboundHasReverseClient(ib *InboundConfig) bool {
+	if ib == nil {
+		return false
+	}
+	var settings struct {
+		Clients []struct {
+			Reverse json.RawMessage `json:"reverse"`
+		} `json:"clients"`
+	}
+	if err := json.Unmarshal(ib.Settings, &settings); err != nil {
+		return false
+	}
+	for _, c := range settings.Clients {
+		if len(c.Reverse) == 0 {
+			continue
+		}
+		var tag any
+		if err := json.Unmarshal(c.Reverse, &tag); err != nil || tag == nil {
+			continue
+		}
+		return true
+	}
+	return false
+}
+
 // diffOutbounds fills diff with outbound removals/additions keyed by tag.
 // The first outbound is xray's default handler and the API can only append,
 // so any change to its identity or content forces a restart. Reordering of