Files
3x-ui/internal/amneziawgnet/resolving_bind_test.go
T
mrchatam 7a41c59494 fix(amneziawg): honor inbound listen when binding UDP socket (#6461)
* fix(amneziawg): honor inbound listen when binding UDP socket

AmneziaWG inbounds ignored the listen field and always opened
awgconn.NewDefaultBind(), so multi-IP hosts replied from the primary
address and handshakes to a secondary IP never completed (#6367).

Carry Inbound.Listen on amneziawg.Instance, open a Bind pinned to that
address (wildcard when empty/0.0.0.0/::), and include listen in
addressFingerprint so edits rebuild the Device.

Fixes #6367

* fix(amneziawg): fall back to wildcard when listen is unusable

Invalid or non-local listen values no longer hard-fail inbound startup;
treat ::0/[::0] as wildcards and normalize listen in the bind fingerprint.

* fix(amneziawg): use ListenConfig.ListenPacket for noctx

---------

Co-authored-by: mrchatam <mrchatam@users.noreply.github.com>
Co-authored-by: mrchatam <287639636+mrchatam@users.noreply.github.com>
2026-09-12 11:11:02 +02:00

76 lines
2.1 KiB
Go

package amneziawgnet
import (
"context"
"errors"
"net/netip"
"testing"
awgconn "github.com/amnezia-vpn/amneziawg-go/v3/conn"
)
func mustResolvingBind(t *testing.T) *resolvingBind {
t.Helper()
return newResolvingBind("")
}
func endpointAddrPort(ep awgconn.Endpoint) netip.AddrPort {
std, ok := ep.(*awgconn.StdNetEndpoint)
if !ok {
panic("unexpected endpoint type")
}
return std.AddrPort
}
func TestResolvingBind_ParseEndpointIPLiteral(t *testing.T) {
b := mustResolvingBind(t)
ep, err := b.ParseEndpoint("203.0.113.7:51820")
if err != nil {
t.Fatalf("IP endpoint rejected: %v", err)
}
got := endpointAddrPort(ep)
if got.Addr().String() != "203.0.113.7" || got.Port() != 51820 {
t.Fatalf("endpoint = %v, want 203.0.113.7:51820", got)
}
}
func TestResolvingBind_ParseEndpointHostnameResolves(t *testing.T) {
orig := lookupEndpointHost
lookupEndpointHost = func(ctx context.Context, host string) ([]netip.Addr, error) {
if host != "peer.example.test" {
t.Errorf("unexpected lookup host %q", host)
}
return []netip.Addr{netip.MustParseAddr("198.51.100.9")}, nil
}
defer func() { lookupEndpointHost = orig }()
b := mustResolvingBind(t)
ep, err := b.ParseEndpoint("peer.example.test:443")
if err != nil {
t.Fatalf("hostname endpoint rejected: %v", err)
}
if got := endpointAddrPort(ep); got.Addr().String() != "198.51.100.9" || got.Port() != 443 {
t.Fatalf("endpoint = %v, want 198.51.100.9:443", got)
}
}
func TestResolvingBind_ParseEndpointResolveFailureIsAnError(t *testing.T) {
orig := lookupEndpointHost
lookupEndpointHost = func(ctx context.Context, host string) ([]netip.Addr, error) {
return nil, errors.New("no such host")
}
defer func() { lookupEndpointHost = orig }()
b := mustResolvingBind(t)
if _, err := b.ParseEndpoint("missing.example.test:80"); err == nil {
t.Fatal("expected resolve failure to surface as an error")
}
}
func TestResolvingBind_ParseEndpointBadPortRejected(t *testing.T) {
b := mustResolvingBind(t)
if _, err := b.ParseEndpoint("203.0.113.7:none"); err == nil {
t.Fatal("expected bad port to be rejected")
}
}