Przeglądaj źródła

web: overlay WireGuard peer public key from the inbound (#6751)

The WireGuard branch now copies PublicKey from the matching inbound
settings client. When that entry's KeepAlive is nil the peer keepalive
is cleared, and when it is set the integer is copied into a new pointer.
The dual-tunnel test seeds different keys and keepalives, checks that
the shared row still has the AmneziaWG identity, and expects the emitted
WireGuard peer to use the WireGuard public key and keepalive, including
a case where the WireGuard settings entry has no keepalive and the peer
omits it.

Fixes #6731
Matt Van Horn 1 dzień temu
rodzic
commit
f217212247

+ 8 - 0
internal/web/service/xray.go

@@ -286,6 +286,14 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
 				if inboundClient, ok := wireguardClientsByEmail[strings.ToLower(strings.TrimSpace(c.Email))]; ok {
 					c.AllowedIPs = inboundClient.AllowedIPs
 					c.PreSharedKey = inboundClient.PreSharedKey
+					c.PublicKey = inboundClient.PublicKey
+					// #6731: a nil settings keepalive must not keep the other tunnel's value.
+					if inboundClient.KeepAlive == nil {
+						c.KeepAlive = nil
+					} else {
+						keepalive := *inboundClient.KeepAlive
+						c.KeepAlive = &keepalive
+					}
 				}
 				wgPeers = append(wgPeers, model.WireguardPeerFromClient(c))
 				continue

+ 38 - 6
internal/web/service/xray_wireguard_config_test.go

@@ -55,7 +55,7 @@ func seedWGInbound(t *testing.T, tag string, port int, clients []model.Client) {
 	}
 }
 
-func seedDualTunnelClient(t *testing.T, enabled bool) string {
+func seedDualTunnelClient(t *testing.T, enabled bool, wgKeepAlive *int) string {
 	t.Helper()
 	setupSettingTestDB(t)
 	db := database.GetDB()
@@ -64,13 +64,16 @@ func seedDualTunnelClient(t *testing.T, enabled bool) string {
 	wgClient := model.Client{
 		Email:        email,
 		Enable:       true,
-		PublicKey:    "pub-dual",
+		PublicKey:    "pub-wg",
 		AllowedIPs:   []string{"10.0.0.5/32"},
 		PreSharedKey: "wg-psk",
+		KeepAlive:    wgKeepAlive,
 	}
 	awgClient := wgClient
+	awgClient.PublicKey = "pub-awg"
 	awgClient.AllowedIPs = []string{"10.8.1.5/32"}
 	awgClient.PreSharedKey = "awg-psk"
+	awgClient.KeepAlive = model.KeepAlivePtr(25)
 
 	wgSettings, err := json.Marshal(map[string]any{
 		"secretKey": wgTestSecretKey(),
@@ -191,14 +194,14 @@ func TestGetXrayConfigWireGuardDisabledClientExcluded(t *testing.T) {
 }
 
 func TestGetXrayConfigWireGuardUsesInboundLocalTunnelFields(t *testing.T) {
-	email := seedDualTunnelClient(t, true)
+	email := seedDualTunnelClient(t, true, model.KeepAlivePtr(15))
 
 	var shared model.ClientRecord
 	if err := database.GetDB().Where("email = ?", email).First(&shared).Error; err != nil {
 		t.Fatalf("read shared client: %v", err)
 	}
-	if shared.AllowedIPs != "10.8.1.5/32" || shared.PreSharedKey != "awg-psk" {
-		t.Fatalf("test setup did not persist AmneziaWG last: allowedIPs=%q preSharedKey=%q", shared.AllowedIPs, shared.PreSharedKey)
+	if shared.AllowedIPs != "10.8.1.5/32" || shared.PreSharedKey != "awg-psk" || shared.PublicKey != "pub-awg" || shared.KeepAlive != 25 {
+		t.Fatalf("test setup did not persist AmneziaWG last: allowedIPs=%q preSharedKey=%q publicKey=%q keepAlive=%d", shared.AllowedIPs, shared.PreSharedKey, shared.PublicKey, shared.KeepAlive)
 	}
 
 	peers := wgPeerList(t, wgInboundEmittedSettings(t, "wg-dual"))
@@ -212,10 +215,39 @@ func TestGetXrayConfigWireGuardUsesInboundLocalTunnelFields(t *testing.T) {
 	if peers[0]["preSharedKey"] != "wg-psk" {
 		t.Fatalf("WireGuard peer preSharedKey = %v, want wg-psk", peers[0]["preSharedKey"])
 	}
+	if peers[0]["publicKey"] != "pub-wg" {
+		t.Fatalf("WireGuard peer publicKey = %v, want pub-wg", peers[0]["publicKey"])
+	}
+	if peers[0]["keepAlive"] != float64(15) {
+		t.Fatalf("WireGuard peer keepAlive = %v, want 15", peers[0]["keepAlive"])
+	}
+}
+
+func TestGetXrayConfigWireGuardOmitsKeepAliveAbsentFromSettings(t *testing.T) {
+	email := seedDualTunnelClient(t, true, nil)
+
+	var shared model.ClientRecord
+	if err := database.GetDB().Where("email = ?", email).First(&shared).Error; err != nil {
+		t.Fatalf("read shared client: %v", err)
+	}
+	if shared.PublicKey != "pub-awg" || shared.KeepAlive != 25 {
+		t.Fatalf("test setup did not persist AmneziaWG identity: publicKey=%q keepAlive=%d", shared.PublicKey, shared.KeepAlive)
+	}
+
+	peers := wgPeerList(t, wgInboundEmittedSettings(t, "wg-dual"))
+	if len(peers) != 1 {
+		t.Fatalf("expected 1 peer, got %d: %v", len(peers), peers)
+	}
+	if peers[0]["publicKey"] != "pub-wg" {
+		t.Fatalf("WireGuard peer publicKey = %v, want pub-wg", peers[0]["publicKey"])
+	}
+	if _, ok := peers[0]["keepAlive"]; ok {
+		t.Fatalf("WireGuard peer keepAlive = %v, want absent", peers[0]["keepAlive"])
+	}
 }
 
 func TestGetXrayConfigWireGuardDisabledDualProtocolClientExcluded(t *testing.T) {
-	seedDualTunnelClient(t, false)
+	seedDualTunnelClient(t, false, model.KeepAlivePtr(15))
 
 	peers := wgPeerList(t, wgInboundEmittedSettings(t, "wg-dual"))
 	if len(peers) != 0 {