xray_wireguard_config_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package service
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "testing"
  6. "github.com/mhsanaei/3x-ui/v3/internal/database"
  7. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  8. )
  9. func wgTestSecretKey() string {
  10. return base64.StdEncoding.EncodeToString(make([]byte, 32))
  11. }
  12. func wgInboundEmittedSettings(t *testing.T, tag string) map[string]any {
  13. t.Helper()
  14. svc := &XrayService{}
  15. cfg, err := svc.GetXrayConfig()
  16. if err != nil {
  17. t.Fatalf("GetXrayConfig: %v", err)
  18. }
  19. for i := range cfg.InboundConfigs {
  20. ic := cfg.InboundConfigs[i]
  21. if ic.Tag != tag {
  22. continue
  23. }
  24. var s map[string]any
  25. if err := json.Unmarshal([]byte(ic.Settings), &s); err != nil {
  26. t.Fatalf("unmarshal emitted settings: %v", err)
  27. }
  28. return s
  29. }
  30. t.Fatalf("inbound %q not found in generated config", tag)
  31. return nil
  32. }
  33. func seedWGInbound(t *testing.T, tag string, port int, clients []model.Client) {
  34. t.Helper()
  35. setupSettingTestDB(t)
  36. db := database.GetDB()
  37. in := &model.Inbound{
  38. Tag: tag,
  39. Enable: true,
  40. Port: port,
  41. Protocol: model.WireGuard,
  42. Settings: `{"secretKey":"` + wgTestSecretKey() + `","mtu":1420}`,
  43. }
  44. if err := db.Create(in).Error; err != nil {
  45. t.Fatalf("create wg inbound: %v", err)
  46. }
  47. svc := ClientService{}
  48. if err := svc.SyncInbound(nil, in.Id, clients); err != nil {
  49. t.Fatalf("SyncInbound: %v", err)
  50. }
  51. }
  52. func wgPeerList(t *testing.T, settings map[string]any) []map[string]any {
  53. t.Helper()
  54. if _, ok := settings["clients"]; ok {
  55. t.Fatalf("wireguard inbound must not emit a clients[] key: %v", settings["clients"])
  56. }
  57. rawPeers, ok := settings["peers"].([]any)
  58. if !ok {
  59. t.Fatalf("settings.peers is not an array: %T", settings["peers"])
  60. }
  61. out := make([]map[string]any, 0, len(rawPeers))
  62. for _, p := range rawPeers {
  63. m, ok := p.(map[string]any)
  64. if !ok {
  65. t.Fatalf("peer is not an object: %T", p)
  66. }
  67. out = append(out, m)
  68. }
  69. return out
  70. }
  71. func TestGetXrayConfigWireGuardPeers(t *testing.T) {
  72. clients := []model.Client{
  73. {Email: "[email protected]", Enable: true, PublicKey: "pub-alice", AllowedIPs: []string{"10.0.0.2/32"}, KeepAlive: 25},
  74. {Email: "[email protected]", Enable: true, PublicKey: "pub-bob", AllowedIPs: []string{"10.0.0.3/32"}},
  75. }
  76. seedWGInbound(t, "wg-multi", 51820, clients)
  77. settings := wgInboundEmittedSettings(t, "wg-multi")
  78. if settings["secretKey"] != wgTestSecretKey() {
  79. t.Errorf("secretKey not preserved: %v", settings["secretKey"])
  80. }
  81. if settings["mtu"] != float64(1420) {
  82. t.Errorf("mtu not preserved: %v", settings["mtu"])
  83. }
  84. peers := wgPeerList(t, settings)
  85. if len(peers) != 2 {
  86. t.Fatalf("expected 2 peers, got %d: %v", len(peers), peers)
  87. }
  88. ips := map[string]bool{}
  89. for _, p := range peers {
  90. if p["email"] == nil || p["email"] == "" {
  91. t.Errorf("peer missing email: %v", p)
  92. }
  93. if p["publicKey"] == nil || p["publicKey"] == "" {
  94. t.Errorf("peer missing publicKey: %v", p)
  95. }
  96. if p["level"] != float64(0) {
  97. t.Errorf("peer level = %v, want 0 (needed for per-user stats)", p["level"])
  98. }
  99. allowed, ok := p["allowedIPs"].([]any)
  100. if !ok || len(allowed) == 0 {
  101. t.Fatalf("peer missing allowedIPs: %v", p)
  102. }
  103. ips[allowed[0].(string)] = true
  104. }
  105. if len(ips) != 2 {
  106. t.Errorf("peers must have distinct allowedIPs, got %v", ips)
  107. }
  108. }
  109. func TestGetXrayConfigWireGuardDisabledClientExcluded(t *testing.T) {
  110. clients := []model.Client{
  111. {Email: "[email protected]", Enable: true, PublicKey: "pub-on", AllowedIPs: []string{"10.0.0.2/32"}},
  112. {Email: "[email protected]", Enable: true, PublicKey: "pub-off", AllowedIPs: []string{"10.0.0.3/32"}},
  113. }
  114. seedWGInbound(t, "wg-disabled", 51821, clients)
  115. if err := database.GetDB().Model(&model.ClientRecord{}).
  116. Where("email = ?", "[email protected]").Update("enable", false).Error; err != nil {
  117. t.Fatalf("disable client: %v", err)
  118. }
  119. peers := wgPeerList(t, wgInboundEmittedSettings(t, "wg-disabled"))
  120. if len(peers) != 1 {
  121. t.Fatalf("expected 1 enabled peer, got %d: %v", len(peers), peers)
  122. }
  123. if peers[0]["email"] != "[email protected]" {
  124. t.Errorf("wrong peer kept: %v", peers[0])
  125. }
  126. }
  127. func TestGetXrayConfigWireGuardNoClientsEmitsEmptyPeers(t *testing.T) {
  128. seedWGInbound(t, "wg-empty", 51822, nil)
  129. settings := wgInboundEmittedSettings(t, "wg-empty")
  130. if _, ok := settings["clients"]; ok {
  131. t.Fatalf("clients key must be absent")
  132. }
  133. peers, ok := settings["peers"].([]any)
  134. if !ok {
  135. t.Fatalf("peers must be an (empty) array, got %T", settings["peers"])
  136. }
  137. if len(peers) != 0 {
  138. t.Fatalf("expected empty peers, got %v", peers)
  139. }
  140. }