|
@@ -0,0 +1,107 @@
|
|
|
|
|
+package amneziawgnet
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "net/netip"
|
|
|
|
|
+ "testing"
|
|
|
|
|
+
|
|
|
|
|
+ "golang.org/x/net/dns/dnsmessage"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+func TestDNSQueryTypesFor(t *testing.T) {
|
|
|
|
|
+ v4 := netip.MustParseAddr("10.8.0.2")
|
|
|
|
|
+ v6 := netip.MustParseAddr("2001:db8::2")
|
|
|
|
|
+ mapped := netip.MustParseAddr("::ffff:10.8.0.2")
|
|
|
|
|
+
|
|
|
|
|
+ cases := []struct {
|
|
|
|
|
+ name string
|
|
|
|
|
+ addrs []netip.Addr
|
|
|
|
|
+ want []dnsmessage.Type
|
|
|
|
|
+ }{
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "v4-only",
|
|
|
|
|
+ addrs: []netip.Addr{v4},
|
|
|
|
|
+ want: []dnsmessage.Type{dnsmessage.TypeA},
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "v6-only",
|
|
|
|
|
+ addrs: []netip.Addr{v6},
|
|
|
|
|
+ want: []dnsmessage.Type{dnsmessage.TypeAAAA},
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "dual-stack prefers A then AAAA",
|
|
|
|
|
+ addrs: []netip.Addr{v4, v6},
|
|
|
|
|
+ want: []dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA},
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "empty falls back to A then AAAA",
|
|
|
|
|
+ addrs: nil,
|
|
|
|
|
+ want: []dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA},
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "v4-mapped alone is not dual-stack",
|
|
|
|
|
+ addrs: []netip.Addr{mapped},
|
|
|
|
|
+ want: []dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA},
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+ for _, tc := range cases {
|
|
|
|
|
+ t.Run(tc.name, func(t *testing.T) {
|
|
|
|
|
+ got := dnsQueryTypesFor(tc.addrs)
|
|
|
|
|
+ if len(got) != len(tc.want) {
|
|
|
|
|
+ t.Fatalf("dnsQueryTypesFor(%v) = %v, want %v", tc.addrs, got, tc.want)
|
|
|
|
|
+ }
|
|
|
|
|
+ for i := range got {
|
|
|
|
|
+ if got[i] != tc.want[i] {
|
|
|
|
|
+ t.Fatalf("dnsQueryTypesFor(%v) = %v, want %v", tc.addrs, got, tc.want)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func TestTunnelSupportsAddr(t *testing.T) {
|
|
|
|
|
+ v4 := netip.MustParseAddr("10.8.0.2")
|
|
|
|
|
+ v6 := netip.MustParseAddr("2001:db8::2")
|
|
|
|
|
+ dest4 := netip.MustParseAddr("8.8.8.8")
|
|
|
|
|
+ dest6 := netip.MustParseAddr("2001:4860:4860::8888")
|
|
|
|
|
+ mappedDest := netip.MustParseAddr("::ffff:8.8.8.8")
|
|
|
|
|
+
|
|
|
|
|
+ if !tunnelSupportsAddr([]netip.Addr{v4}, dest4) {
|
|
|
|
|
+ t.Error("v4 tunnel should dial IPv4")
|
|
|
|
|
+ }
|
|
|
|
|
+ if tunnelSupportsAddr([]netip.Addr{v4}, dest6) {
|
|
|
|
|
+ t.Error("v4-only tunnel must not dial IPv6")
|
|
|
|
|
+ }
|
|
|
|
|
+ if !tunnelSupportsAddr([]netip.Addr{v6}, dest6) {
|
|
|
|
|
+ t.Error("v6 tunnel should dial IPv6")
|
|
|
|
|
+ }
|
|
|
|
|
+ if tunnelSupportsAddr([]netip.Addr{v6}, dest4) {
|
|
|
|
|
+ t.Error("v6-only tunnel must not dial IPv4")
|
|
|
|
|
+ }
|
|
|
|
|
+ if !tunnelSupportsAddr([]netip.Addr{v4, v6}, dest4) || !tunnelSupportsAddr([]netip.Addr{v4, v6}, dest6) {
|
|
|
|
|
+ t.Error("dual-stack tunnel should dial both families")
|
|
|
|
|
+ }
|
|
|
|
|
+ if !tunnelSupportsAddr([]netip.Addr{v4}, mappedDest) {
|
|
|
|
|
+ t.Error("v4 tunnel should treat IPv4-mapped destinations as IPv4")
|
|
|
|
|
+ }
|
|
|
|
|
+ if tunnelSupportsAddr(nil, dest4) {
|
|
|
|
|
+ t.Error("empty address list should not claim support")
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func TestSocksTargetResolveTunnelVia_RejectsWrongFamilyLiteral(t *testing.T) {
|
|
|
|
|
+ dev := &Device{localAddrs: []netip.Addr{netip.MustParseAddr("10.8.0.2")}}
|
|
|
|
|
+ target := socksTarget{ip: netip.MustParseAddr("2001:4860:4860::8888"), port: 443}
|
|
|
|
|
+ _, err := target.resolveTunnelVia("", "awg", dev)
|
|
|
|
|
+ if err == nil {
|
|
|
|
|
+ t.Fatal("expected error dialing IPv6 literal on v4-only tunnel")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ okTarget := socksTarget{ip: netip.MustParseAddr("8.8.8.8"), port: 443}
|
|
|
|
|
+ got, err := okTarget.resolveTunnelVia("", "awg", dev)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ t.Fatalf("v4 literal on v4 tunnel: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if got.String() != "8.8.8.8:443" {
|
|
|
|
|
+ t.Fatalf("got %s", got)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|