Просмотр исходного кода

fix(job): force-disconnect over-limit Hysteria2 clients

disconnectClientTemporarily still gated on the protocol list from before
XrayAPI.AddUser learned hysteria, so an over-limit Hysteria2 client kept
its QUIC session until the fail2ban ban aged out, while a VLESS client in
the same situation was dropped at once. buildUserAccount handles hysteria
and model.Client already marshals the auth field the re-add needs, so admit
the protocol. wireguard stays excluded: its keepAlive marshals as a JSON
number, which the string-only user-field parsing rejects after the user was
already removed.

Closes #6256
Sanaei 11 часов назад
Родитель
Сommit
d175050f2e
2 измененных файлов с 45 добавлено и 2 удалено
  1. 3 2
      internal/web/job/check_client_ip_job.go
  2. 42 0
      internal/web/job/limit_ip_disconnect_test.go

+ 3 - 2
internal/web/job/check_client_ip_job.go

@@ -634,10 +634,11 @@ func (j *CheckClientIpJob) disconnectClientTemporarily(inbound *model.Inbound, c
 		return
 		return
 	}
 	}
 
 
-	// Only perform remove/re-add for protocols supported by XrayAPI.AddUser
+	// Protocols XrayAPI can remove and re-add from a marshaled model.Client.
+	// wireguard stays out: keepAlive marshals as a number, AddUser wants a string.
 	protocol := string(inbound.Protocol)
 	protocol := string(inbound.Protocol)
 	switch protocol {
 	switch protocol {
-	case "vmess", "vless", "trojan", "shadowsocks":
+	case "vmess", "vless", "trojan", "shadowsocks", "hysteria":
 		// supported protocols, continue
 		// supported protocols, continue
 	default:
 	default:
 		logger.Warningf("[LIMIT_IP] Temporary disconnect is not supported for protocol %s on inbound %s", protocol, inbound.Tag)
 		logger.Warningf("[LIMIT_IP] Temporary disconnect is not supported for protocol %s on inbound %s", protocol, inbound.Tag)

+ 42 - 0
internal/web/job/limit_ip_disconnect_test.go

@@ -0,0 +1,42 @@
+package job
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/mhsanaei/3x-ui/v3/internal/database/model"
+	"github.com/mhsanaei/3x-ui/v3/internal/logger"
+)
+
+// The protocol gate must let hysteria through: XrayAPI supports it, and the
+// skip left over-limit Hysteria2 sessions alive until the fail2ban ban caught up.
+func TestDisconnectClientTemporarilyAllowsHysteria(t *testing.T) {
+	setupIntegrationDB(t)
+
+	const email = "hy2-limit-probe"
+	inbound := &model.Inbound{
+		Id:       1,
+		Protocol: model.Hysteria,
+		Tag:      "hy2-limit-probe-tag",
+		Settings: `{"clients":[]}`,
+	}
+	clients := []model.Client{{Email: email, Auth: "secret"}}
+
+	(&CheckClientIpJob{}).disconnectClientTemporarily(inbound, email, clients)
+
+	var unsupported, attempted bool
+	for _, line := range logger.GetLogs(500, "warning") {
+		if strings.Contains(line, "Temporary disconnect is not supported for protocol hysteria") {
+			unsupported = true
+		}
+		if strings.Contains(line, "Failed to remove user "+email) {
+			attempted = true
+		}
+	}
+	if unsupported {
+		t.Fatal("hysteria was rejected by the protocol gate")
+	}
+	if !attempted {
+		t.Fatal("expected a remove attempt against the Xray API for hysteria")
+	}
+}