diff --git a/internal/util/link/outbound.go b/internal/util/link/outbound.go index 5a64164b5..930cfc97c 100644 --- a/internal/util/link/outbound.go +++ b/internal/util/link/outbound.go @@ -10,6 +10,7 @@ import ( "fmt" "maps" "math" + "net" "net/url" "regexp" "slices" @@ -657,7 +658,7 @@ func parseWireguard(link string) (*ParseResult, error) { portStr := u.Port() endpoint := host if portStr != "" { - endpoint = host + ":" + portStr + endpoint = net.JoinHostPort(host, portStr) } addrRaw := firstParam(params, "address", "ip") diff --git a/internal/util/link/outbound_helpers_test.go b/internal/util/link/outbound_helpers_test.go index 254c891f8..d8755dc1f 100644 --- a/internal/util/link/outbound_helpers_test.go +++ b/internal/util/link/outbound_helpers_test.go @@ -431,6 +431,28 @@ func TestParse_VmessFinalMask(t *testing.T) { } } +func TestParseWireguard_Endpoint(t *testing.T) { + cases := []struct { + link string + want string + }{ + {"wireguard://key@a.com:51820?publickey=pub#x", "a.com:51820"}, + {"wireguard://key@1.2.3.4:51820?publickey=pub#x", "1.2.3.4:51820"}, + {"wireguard://key@[2001:db8::1]:51820?publickey=pub#x", "[2001:db8::1]:51820"}, + {"wireguard://key@a.com?publickey=pub#x", "a.com"}, + } + for _, c := range cases { + res, err := ParseLink(c.link) + if err != nil { + t.Fatalf("parse %s: %v", c.link, err) + } + peer := res.Outbound["settings"].(map[string]any)["peers"].([]any)[0].(map[string]any) + if peer["endpoint"] != c.want { + t.Errorf("%s: endpoint = %v, want %q", c.link, peer["endpoint"], c.want) + } + } +} + func TestParse_RemarkDecodedOnce(t *testing.T) { // Remarks as the subscription server writes them (encodeURIComponent). cases := []struct {