mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-11 15:45:00 +03:00
b3a5be9da4
* fix(amneziawg): stop AAAA fallback on v4-only tunnels and expose I2–I5 Gate tunnel DNS queries to address families the device can actually dial, reject undialable literal IPs early, and surface I2–I5 on the outbound form. Fixes #6570 * ci: retrigger frontend after npm registry maintenance The frontend job failed solely on `npm audit` while registry.npmjs.org returned 503 (Service Under Maintenance). Lint, typecheck, vitest, vite build, and storybook all passed. Local `npm audit --omit=dev --audit-level=high` now reports 0 vulnerabilities. * style(amneziawg): keep the tunnel DNS family comments to two lines CLAUDE.md caps a comment block at two lines. --------- Co-authored-by: mrchatam <mrchatam@users.noreply.github.com> Co-authored-by: MHSanaei <ho3ein.sanaei@gmail.com>
108 lines
3.0 KiB
Go
108 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|