| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package sub
- import (
- "fmt"
- "strings"
- "testing"
- "github.com/mhsanaei/3x-ui/v3/internal/database"
- "github.com/mhsanaei/3x-ui/v3/internal/database/model"
- )
- func seedTunnelSubInbound(t *testing.T, protocol model.Protocol, tag, subID, email, settings string, port int) *model.Inbound {
- t.Helper()
- db := database.GetDB()
- ib := &model.Inbound{
- UserId: 1, Tag: tag, Enable: true, Listen: "203.0.113.5", Port: port,
- Protocol: protocol, Remark: tag, Settings: settings,
- }
- if err := db.Create(ib).Error; err != nil {
- t.Fatalf("create %s: %v", tag, err)
- }
- rec := &model.ClientRecord{Email: email, SubID: subID, Enable: true}
- if err := db.Create(rec).Error; err != nil {
- t.Fatalf("create client: %v", err)
- }
- if err := db.Create(&model.ClientInbound{ClientId: rec.Id, InboundId: ib.Id}).Error; err != nil {
- t.Fatalf("link client: %v", err)
- }
- return ib
- }
- // A Host on a WireGuard inbound must replace the advertised endpoint; the raw
- // generator used to ignore it and always emit the panel's own address.
- func TestGetSubs_WireGuardAdvertisesHostEndpoints(t *testing.T) {
- initSubDB(t)
- serverPriv, _ := mustWireguardKeypair(t)
- clientPriv, _ := mustWireguardKeypair(t)
- const email, subID = "alice@wg", "sub-wg-hosts"
- settings := fmt.Sprintf(`{"secretKey":%q,"clients":[{"email":%q,"privateKey":%q,"allowedIPs":["10.0.0.2/32"],"enable":true}]}`,
- serverPriv, email, clientPriv)
- ib := seedTunnelSubInbound(t, model.WireGuard, "wg-in", subID, email, settings, 51820)
- seedHost(t, &model.Host{InboundId: ib.Id, SortOrder: 2, Remark: "CDN-B", Address: "wg2.example.com"})
- seedHost(t, &model.Host{InboundId: ib.Id, SortOrder: 1, Remark: "CDN-A", Address: "wg.example.com", Port: 443})
- links, _, _, _, err := NewSubService("").GetSubs(subID, "sub.example.com")
- if err != nil {
- t.Fatalf("GetSubs: %v", err)
- }
- parts := splitLinkLines(strings.Join(links, "\n"))
- want := []struct{ host, remark string }{
- {"wg.example.com:443", "wg-in-CDN-A-" + email},
- {"wg2.example.com:51820", "wg-in-CDN-B-" + email},
- }
- if len(parts) != len(want) {
- t.Fatalf("links = %d, want %d: %v", len(parts), len(want), parts)
- }
- for i, w := range want {
- u := parseWireguardSubLink(t, parts[i])
- if u.Host != w.host || u.Fragment != w.remark {
- t.Fatalf("link %d = %s#%s, want %s#%s", i, u.Host, u.Fragment, w.host, w.remark)
- }
- if u.User.Username() != clientPriv {
- t.Fatalf("link %d private key = %q, want the client's", i, u.User.Username())
- }
- }
- }
- // The AmneziaWG vpn:// payload carries the endpoint inside its .conf text, so a
- // Host must reach the Endpoint line and the remark comment, not only the URL.
- func TestGetSubs_AmneziaWGAdvertisesHostEndpoint(t *testing.T) {
- initSubDB(t)
- serverPriv, serverPub := mustWireguardKeypair(t)
- clientPriv, _ := mustWireguardKeypair(t)
- const email, subID = "alice@awg", "sub-awg-hosts"
- settings := fmt.Sprintf(`{"server":{"privateKey":%q,"publicKey":%q,"mtu":1420},"clients":[{"email":%q,"privateKey":%q,"allowedIPs":["10.8.0.2/32"],"enable":true}]}`,
- serverPriv, serverPub, email, clientPriv)
- ib := seedTunnelSubInbound(t, model.AmneziaWG, "awg-in", subID, email, settings, 51821)
- seedHost(t, &model.Host{InboundId: ib.Id, SortOrder: 1, Remark: "CDN", Address: "awg.example.com", Port: 8443})
- links, _, _, _, err := NewSubService("").GetSubs(subID, "sub.example.com")
- if err != nil {
- t.Fatalf("GetSubs: %v", err)
- }
- parts := splitLinkLines(strings.Join(links, "\n"))
- if len(parts) != 1 {
- t.Fatalf("links = %d, want 1: %v", len(parts), parts)
- }
- conf := decodeAmneziaWGSubLink(t, parts[0])
- for _, line := range []string{"Endpoint = awg.example.com:8443", "# awg-in-CDN-" + email, "PrivateKey = " + clientPriv} {
- if !strings.Contains(conf, line) {
- t.Fatalf("config missing %q\n%s", line, conf)
- }
- }
- if strings.Contains(conf, "203.0.113.5") {
- t.Fatalf("config still advertises the inbound address\n%s", conf)
- }
- }
|