| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- package amneziawgnet
- import (
- "strings"
- "testing"
- "github.com/mhsanaei/3x-ui/v3/internal/amneziawg"
- wgutil "github.com/mhsanaei/3x-ui/v3/internal/util/wireguard"
- )
- // clientDeviceTestInstance builds a minimal valid client instance with one
- // peer and a non-zero keepalive -- the exact shape the outbound form seeds.
- func clientDeviceTestInstance(t *testing.T) amneziawg.OutboundInstance {
- t.Helper()
- priv, pub, err := wgutil.GenerateWireguardKeypair()
- if err != nil {
- t.Fatal(err)
- }
- return amneziawg.OutboundInstance{
- Tag: "awg-out-test",
- Address: []string{"10.8.0.2/32"},
- MTU: 1420,
- PrivateKey: priv,
- Peers: []amneziawg.OutboundPeer{{
- PublicKey: pub,
- AllowedIPs: []string{"0.0.0.0/0", "::/0"},
- Endpoint: "203.0.113.7:51820",
- KeepAlive: 25,
- }},
- }
- }
- func TestBuildClientUAPIConfig_KeepAliveKeyIsValidUAPIPeerKey(t *testing.T) {
- inst := clientDeviceTestInstance(t)
- conf, err := buildClientUAPIConfig(inst, DeviceOptions{})
- if err != nil {
- t.Fatal(err)
- }
- want := "persistent_keepalive_interval=25\n"
- if !strings.Contains(conf, want) {
- t.Fatalf("UAPI config missing %q:\n%s", want, conf)
- }
- if strings.Contains(conf, "persistent_keepalive_seconds") {
- t.Fatalf("UAPI config contains invalid peer key persistent_keepalive_seconds:\n%s", conf)
- }
- }
- func TestBuildClientUAPIConfig_ZeroKeepAliveOmitsLine(t *testing.T) {
- inst := clientDeviceTestInstance(t)
- inst.Peers[0].KeepAlive = 0
- conf, err := buildClientUAPIConfig(inst, DeviceOptions{})
- if err != nil {
- t.Fatal(err)
- }
- if strings.Contains(conf, "persistent_keepalive") {
- t.Fatalf("zero KeepAlive must not emit a keepalive line:\n%s", conf)
- }
- }
- // amneziawg-go reads an absent UAPI line as "keep the current value", and
- // ensureLocked reconfigures in place, so a cleared key must be sent as zero.
- func TestBuildClientUAPIConfig_ClearedHeaderProtectionKeyIsSentAsZero(t *testing.T) {
- inst := clientDeviceTestInstance(t)
- inst.Obfuscation = amneziawg.Obfuscation31{S1: 20, S2: 20, S3: 20, S4: 20}
- key, err := wgutil.GenerateWireguardPSK()
- if err != nil {
- t.Fatal(err)
- }
- withKey, err := buildClientUAPIConfig(inst, DeviceOptions{HeaderProtectionKey: key})
- if err != nil {
- t.Fatal(err)
- }
- keyHex, err := wgutil.KeyToHex(key)
- if err != nil {
- t.Fatal(err)
- }
- if !strings.Contains(withKey, "header_protection_key="+keyHex+"\n") {
- t.Fatalf("a set key must be emitted verbatim, got:\n%s", withKey)
- }
- cleared, err := buildClientUAPIConfig(inst, DeviceOptions{})
- if err != nil {
- t.Fatal(err)
- }
- zero := "header_protection_key=" + strings.Repeat("0", 64) + "\n"
- if !strings.Contains(cleared, zero) {
- t.Fatalf("an unset key must be emitted as the all-zero key, got:\n%s", cleared)
- }
- }
- // With no explicit MTU the netstack is built from S4, so an S4-only edit must
- // move the fingerprint or ensureLocked reconfigures in place and keeps the old.
- func TestOutboundFingerprintTracksTheS4DerivedMTU(t *testing.T) {
- tests := []struct {
- name string
- mtu int
- wantChange bool
- }{
- {"derived MTU", 0, true},
- {"explicit MTU", 1420, false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- inst := clientDeviceTestInstance(t)
- inst.MTU = tt.mtu
- inst.Obfuscation.S4 = 12
- before := outboundFingerprint(inst)
- inst.Obfuscation.S4 = 28
- after := outboundFingerprint(inst)
- if changed := before != after; changed != tt.wantChange {
- t.Fatalf("fingerprint changed = %v, want %v (%q -> %q)", changed, tt.wantChange, before, after)
- }
- })
- }
- }
|