mirror of
https://github.com/AdguardTeam/dnsproxy.git
synced 2026-10-11 22:09:55 +00:00
AGH-148 Imp-proxy-tests-vol.4 (30)
This commit is contained in:
@@ -30,6 +30,9 @@ const (
|
||||
// Host is a common host for tests.
|
||||
Host = "test.example"
|
||||
|
||||
// FQDN is the fully-qualified domain name for [Host].
|
||||
FQDN = Host + "."
|
||||
|
||||
// TTL is a common time-to-live value in seconds for tests.
|
||||
TTL = 300
|
||||
)
|
||||
@@ -38,6 +41,12 @@ var (
|
||||
// LocalhostAnyPort is a [netip.AddrPort] having a value of 127.0.0.1:0.
|
||||
LocalhostAnyPort = netip.AddrPortFrom(netutil.IPv4Localhost(), 0)
|
||||
|
||||
// LocalhostAnyPortUDP is a [net.UDPAddr] for [LocalhostAnyPort].
|
||||
LocalhostAnyPortUDP = net.UDPAddrFromAddrPort(LocalhostAnyPort)
|
||||
|
||||
// LocalhostAnyPortTCP is a [net.TCPAddr] for [LocalhostAnyPort].
|
||||
LocalhostAnyPortTCP = net.TCPAddrFromAddrPort(LocalhostAnyPort)
|
||||
|
||||
// IPv4 is a common IPv4 address for tests.
|
||||
IPv4 = net.IPv4(192, 0, 2, 1)
|
||||
)
|
||||
@@ -104,3 +113,50 @@ func RequireResponse(tb testing.TB, req, reply *dns.Msg) {
|
||||
|
||||
require.Equal(tb, IPv4, a.A.To16())
|
||||
}
|
||||
|
||||
// NewRR is a helper that creates a new dns.RR with the given name, qtype, ttl
|
||||
// and value. It fails the test if the qtype is not supported or the type of
|
||||
// value doesn't match the qtype. val is expected to be of type [net.IP] if
|
||||
// qtype is [dns.TypeA] or [dns.TypeAAAA] and a string if qtype is
|
||||
// [dns.TypeCNAME] or [dns.TypePTR]. qtype is expected to be one of the
|
||||
// following:
|
||||
// - [dns.TypeA]
|
||||
// - [dns.TypeAAAA]
|
||||
// - [dns.TypeCNAME]
|
||||
// - [dns.TypeSOA]
|
||||
// - [dns.TypePTR]
|
||||
func NewRR(tb testing.TB, name string, qtype uint16, ttl uint32, val any) (rr dns.RR) {
|
||||
tb.Helper()
|
||||
|
||||
switch qtype {
|
||||
case dns.TypeA:
|
||||
rr = &dns.A{A: testutil.RequireTypeAssert[net.IP](tb, val)}
|
||||
case dns.TypeAAAA:
|
||||
rr = &dns.AAAA{AAAA: testutil.RequireTypeAssert[net.IP](tb, val)}
|
||||
case dns.TypeCNAME:
|
||||
rr = &dns.CNAME{Target: testutil.RequireTypeAssert[string](tb, val)}
|
||||
case dns.TypeSOA:
|
||||
rr = &dns.SOA{
|
||||
Ns: "ns." + name,
|
||||
Mbox: "hostmaster." + name,
|
||||
Serial: 1,
|
||||
Refresh: 1,
|
||||
Retry: 1,
|
||||
Expire: 1,
|
||||
Minttl: 1,
|
||||
}
|
||||
case dns.TypePTR:
|
||||
rr = &dns.PTR{Ptr: testutil.RequireTypeAssert[string](tb, val)}
|
||||
default:
|
||||
tb.Fatalf("unsupported qtype: %d", qtype)
|
||||
}
|
||||
|
||||
*rr.Header() = dns.RR_Header{
|
||||
Name: name,
|
||||
Rrtype: qtype,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: ttl,
|
||||
}
|
||||
|
||||
return rr
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TODO(f.setrakov): Externalize when ECS helpers are moved to golibs.
|
||||
func TestProxy_IsBogusNXDomain(t *testing.T) {
|
||||
var ans []dns.RR
|
||||
|
||||
@@ -24,8 +25,8 @@ func TestProxy_IsBogusNXDomain(t *testing.T) {
|
||||
|
||||
prx := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: upsConf,
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
CacheEnabled: true,
|
||||
|
||||
@@ -52,10 +52,12 @@ func newTestCache(tb testing.TB, conf *cacheConfig) (c *cache) {
|
||||
|
||||
func TestServeCached(t *testing.T) {
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
DNSSECEnabled: false,
|
||||
CacheEnabled: true,
|
||||
@@ -70,7 +72,7 @@ func TestServeCached(t *testing.T) {
|
||||
|
||||
// Fill the cache.
|
||||
reply := (&dns.Msg{
|
||||
Answer: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
}).SetReply(request)
|
||||
reply.SetEdns0(defaultUDPBufSize, false)
|
||||
|
||||
@@ -191,7 +193,7 @@ func TestCacheDO(t *testing.T) {
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Response: true,
|
||||
},
|
||||
Answer: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
}).SetQuestion("google.com.", dns.TypeA)
|
||||
reply.SetEdns0(4096, false)
|
||||
|
||||
@@ -229,7 +231,9 @@ func TestCacheCNAME(t *testing.T) {
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Response: true,
|
||||
},
|
||||
Answer: []dns.RR{newRR(t, "google.com.", dns.TypeCNAME, 3600, "test.google.com.")},
|
||||
Answer: []dns.RR{
|
||||
dnsproxytest.NewRR(t, "google.com.", dns.TypeCNAME, 3600, "test.google.com."),
|
||||
},
|
||||
}).SetQuestion("google.com.", dns.TypeA)
|
||||
testCache.set(request, reply, upstreamWithAddr, testLogger)
|
||||
|
||||
@@ -240,7 +244,10 @@ func TestCacheCNAME(t *testing.T) {
|
||||
})
|
||||
|
||||
// Now fill the cache with a cacheable CNAME response.
|
||||
reply.Answer = append(reply.Answer, newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8}))
|
||||
reply.Answer = append(
|
||||
reply.Answer,
|
||||
dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8}),
|
||||
)
|
||||
testCache.set(request, reply, upstreamWithAddr, testLogger)
|
||||
|
||||
// We are testing that a proper CNAME response gets cached
|
||||
@@ -305,10 +312,12 @@ func TestCacheExpiration(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
CacheEnabled: true,
|
||||
})
|
||||
@@ -317,9 +326,9 @@ func TestCacheExpiration(t *testing.T) {
|
||||
|
||||
// Create dns messages with TTL of 1 second.
|
||||
rrs := []dns.RR{
|
||||
newRR(t, "youtube.com.", dns.TypeA, 1, net.IP{173, 194, 221, 198}),
|
||||
newRR(t, "google.com.", dns.TypeA, 1, net.IP{8, 8, 8, 8}),
|
||||
newRR(t, "yandex.com.", dns.TypeA, 1, net.IP{213, 180, 204, 62}),
|
||||
dnsproxytest.NewRR(t, "youtube.com.", dns.TypeA, 1, net.IP{173, 194, 221, 198}),
|
||||
dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 1, net.IP{8, 8, 8, 8}),
|
||||
dnsproxytest.NewRR(t, "yandex.com.", dns.TypeA, 1, net.IP{213, 180, 204, 62}),
|
||||
}
|
||||
requests := make([]*dns.Msg, 0, len(rrs))
|
||||
responses := make([]*dns.Msg, 0, len(rrs))
|
||||
@@ -367,8 +376,8 @@ func TestCacheExpirationWithTTLOverride(t *testing.T) {
|
||||
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{u},
|
||||
},
|
||||
@@ -455,13 +464,13 @@ func TestCache(t *testing.T) {
|
||||
testCases{
|
||||
cache: []testEntry{{
|
||||
q: "google.com.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}},
|
||||
cases: []testCase{{
|
||||
ok: require.True,
|
||||
q: "google.com.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}, {
|
||||
ok: require.False,
|
||||
@@ -475,23 +484,23 @@ func TestCache(t *testing.T) {
|
||||
testCases{
|
||||
cache: []testEntry{{
|
||||
q: "gOOgle.com.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}},
|
||||
cases: []testCase{{
|
||||
ok: require.True,
|
||||
q: "gOOgle.com.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}, {
|
||||
ok: require.True,
|
||||
q: "google.com.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}, {
|
||||
ok: require.True,
|
||||
q: "GOOGLE.COM.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 3600, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}, {
|
||||
q: "gOOgle.com.",
|
||||
@@ -513,7 +522,7 @@ func TestCache(t *testing.T) {
|
||||
testCases{
|
||||
cache: []testEntry{{
|
||||
q: "gOOgle.com.",
|
||||
a: []dns.RR{newRR(t, "google.com.", dns.TypeA, 0, net.IP{8, 8, 8, 8})},
|
||||
a: []dns.RR{dnsproxytest.NewRR(t, "google.com.", dns.TypeA, 0, net.IP{8, 8, 8, 8})},
|
||||
t: dns.TypeA,
|
||||
}},
|
||||
cases: []testCase{{
|
||||
@@ -630,7 +639,7 @@ func setAndGetCache(t *testing.T, c *cache, g *sync.WaitGroup, host, ip string)
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Response: true,
|
||||
},
|
||||
Answer: []dns.RR{newRR(t, host, dns.TypeA, 1, ipAddr)},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, host, dns.TypeA, 1, ipAddr)},
|
||||
}).SetQuestion(host, dns.TypeA)
|
||||
|
||||
c.set(req, dnsMsg, upstreamWithAddr, testLogger)
|
||||
@@ -670,7 +679,7 @@ func TestCache_getWithSubnet(t *testing.T) {
|
||||
|
||||
// Add a response with subnet.
|
||||
resp := (&dns.Msg{
|
||||
Answer: []dns.RR{newRR(t, testFQDN, dns.TypeA, 1, net.IP{1, 1, 1, 1})},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, testFQDN, dns.TypeA, 1, net.IP{1, 1, 1, 1})},
|
||||
}).SetReply(req)
|
||||
c.setWithSubnet(req, resp, upstreamWithAddr, &net.IPNet{IP: ip1234, Mask: mask16}, testLogger)
|
||||
|
||||
@@ -683,13 +692,13 @@ func TestCache_getWithSubnet(t *testing.T) {
|
||||
|
||||
// Add a response entry with subnet #2.
|
||||
resp = (&dns.Msg{
|
||||
Answer: []dns.RR{newRR(t, testFQDN, dns.TypeA, 1, net.IP{2, 2, 2, 2})},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, testFQDN, dns.TypeA, 1, net.IP{2, 2, 2, 2})},
|
||||
}).SetReply(req)
|
||||
c.setWithSubnet(req, resp, upstreamWithAddr, &net.IPNet{IP: ip2234, Mask: mask16}, testLogger)
|
||||
|
||||
// Add a response entry without subnet.
|
||||
resp = (&dns.Msg{
|
||||
Answer: []dns.RR{newRR(t, testFQDN, dns.TypeA, 1, net.IP{3, 3, 3, 3})},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, testFQDN, dns.TypeA, 1, net.IP{3, 3, 3, 3})},
|
||||
}).SetReply(req)
|
||||
c.setWithSubnet(req, resp, upstreamWithAddr, &net.IPNet{IP: nil, Mask: nil}, testLogger)
|
||||
|
||||
@@ -753,7 +762,7 @@ func TestCache_getWithSubnet_mask(t *testing.T) {
|
||||
|
||||
req := (&dns.Msg{}).SetQuestion(testFQDN, dns.TypeA)
|
||||
resp := (&dns.Msg{
|
||||
Answer: []dns.RR{newRR(t, testFQDN, dns.TypeA, 300, ansIP)},
|
||||
Answer: []dns.RR{dnsproxytest.NewRR(t, testFQDN, dns.TypeA, 300, ansIP)},
|
||||
}).SetReply(req)
|
||||
|
||||
// Cache IP network that contains the testIP.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package proxy
|
||||
package proxy_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/dnsproxytest"
|
||||
proxytest "github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
@@ -17,11 +19,14 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const ipv4OnlyFqdn = "ipv4.only."
|
||||
// testSynTTL is a common TTL for DNS64 synthesized records.
|
||||
const testSynTTL uint32 = 600
|
||||
|
||||
func TestProxy_HandleDNSRequest_dns64Race(t *testing.T) {
|
||||
ans := newRR(t, ipv4OnlyFqdn, dns.TypeA, 3600, dnsproxytest.IPv4)
|
||||
ups := &testUpstream{
|
||||
fakeHost := "fake.address"
|
||||
|
||||
ans := proxytest.NewRR(t, proxytest.FQDN, dns.TypeA, 3600, proxytest.IPv4)
|
||||
ups := &dnsproxytest.Upstream{
|
||||
OnExchange: func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
resp = (&dns.Msg{}).SetReply(req)
|
||||
if req.Question[0].Qtype == dns.TypeA {
|
||||
@@ -30,53 +35,55 @@ func TestProxy_HandleDNSRequest_dns64Race(t *testing.T) {
|
||||
|
||||
return resp, nil
|
||||
},
|
||||
OnAddress: func() (addr string) { return "fake.address" },
|
||||
OnAddress: func() (addr string) { return fakeHost },
|
||||
OnClose: func() (err error) { return nil },
|
||||
}
|
||||
localUps := &testUpstream{
|
||||
localUps := &dnsproxytest.Upstream{
|
||||
OnExchange: func(ctx context.Context, m *dns.Msg) (_ *dns.Msg, _ error) {
|
||||
panic(testutil.UnexpectedCall(ctx, m))
|
||||
},
|
||||
OnAddress: func() (addr string) { return "fake.address" },
|
||||
OnAddress: func() (addr string) { return fakeHost },
|
||||
OnClose: func() (err error) { return nil },
|
||||
}
|
||||
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
PrivateSubnets: netutil.SubnetSetFunc(netutil.IsLocallyServed),
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{ups},
|
||||
},
|
||||
PrivateRDNSUpstreamConfig: &UpstreamConfig{
|
||||
PrivateRDNSUpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{localUps},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
|
||||
UseDNS64: true,
|
||||
UsePrivateRDNS: true,
|
||||
// Valid NAT-64 prefix for 2001:67c:27e4:15::64 server.
|
||||
DNS64Prefs: []netip.Prefix{netip.MustParsePrefix("2001:67c:27e4:1064::/96")},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
servicetest.RequireRun(t, dnsProxy, dnsproxytest.Timeout)
|
||||
servicetest.RequireRun(t, dnsProxy, proxytest.Timeout)
|
||||
|
||||
syncCh := make(chan struct{})
|
||||
|
||||
// Send requests.
|
||||
g := &sync.WaitGroup{}
|
||||
g.Add(dnsproxytest.MessageCount)
|
||||
g.Add(proxytest.MessageCount)
|
||||
|
||||
addr := dnsProxy.Addr(ProtoTCP).String()
|
||||
for range dnsproxytest.MessageCount {
|
||||
addr := dnsProxy.Addr(proxy.ProtoTCP).String()
|
||||
for range proxytest.MessageCount {
|
||||
// The [dns.Conn] isn't safe for concurrent use despite the requirements
|
||||
// from the [net.Conn] documentation.
|
||||
conn, err := dns.Dial("tcp", addr)
|
||||
var conn *dns.Conn
|
||||
conn, err = dns.Dial("tcp", addr)
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, conn.Close)
|
||||
|
||||
go exchangeTestAAAARequestAsync(t, conn, g, ipv4OnlyFqdn, syncCh)
|
||||
go exchangeTestAAAARequestAsync(t, conn, g, proxytest.FQDN, syncCh)
|
||||
}
|
||||
|
||||
close(syncCh)
|
||||
@@ -113,50 +120,12 @@ func exchangeTestAAAARequestAsync(
|
||||
require.IsType(pt, &dns.AAAA{}, res.Answer[0])
|
||||
}
|
||||
|
||||
// newRR is a helper that creates a new dns.RR with the given name, qtype,
|
||||
// ttl and value. It fails the test if the qtype is not supported or the type
|
||||
// of value doesn't match the qtype.
|
||||
func newRR(tb testing.TB, name string, qtype uint16, ttl uint32, val any) (rr dns.RR) {
|
||||
tb.Helper()
|
||||
|
||||
switch qtype {
|
||||
case dns.TypeA:
|
||||
rr = &dns.A{A: testutil.RequireTypeAssert[net.IP](tb, val)}
|
||||
case dns.TypeAAAA:
|
||||
rr = &dns.AAAA{AAAA: testutil.RequireTypeAssert[net.IP](tb, val)}
|
||||
case dns.TypeCNAME:
|
||||
rr = &dns.CNAME{Target: testutil.RequireTypeAssert[string](tb, val)}
|
||||
case dns.TypeSOA:
|
||||
rr = &dns.SOA{
|
||||
Ns: "ns." + name,
|
||||
Mbox: "hostmaster." + name,
|
||||
Serial: 1,
|
||||
Refresh: 1,
|
||||
Retry: 1,
|
||||
Expire: 1,
|
||||
Minttl: 1,
|
||||
}
|
||||
case dns.TypePTR:
|
||||
rr = &dns.PTR{Ptr: testutil.RequireTypeAssert[string](tb, val)}
|
||||
default:
|
||||
tb.Fatalf("unsupported qtype: %d", qtype)
|
||||
}
|
||||
|
||||
*rr.Header() = dns.RR_Header{
|
||||
Name: name,
|
||||
Rrtype: qtype,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: ttl,
|
||||
}
|
||||
|
||||
return rr
|
||||
}
|
||||
|
||||
// TODO(e.burkov): Refactor the test.
|
||||
// TODO(f.setrakov): Refactor the test.
|
||||
func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
someIPv4 := net.IP{1, 2, 3, 4}
|
||||
someIPv6 := net.IP{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
||||
mappedIPv6 := net.ParseIP("64:ff9b::102:304")
|
||||
filteredIPv6 := net.ParseIP("64:ff9b::506:708")
|
||||
|
||||
ptr64Domain, err := netutil.IPToReversedAddr(mappedIPv6)
|
||||
require.NoError(t, err)
|
||||
@@ -166,8 +135,6 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
ptrGlobDomain = dns.Fqdn(ptrGlobDomain)
|
||||
|
||||
localCliAddr := netip.MustParseAddrPort("192.168.1.1:1234")
|
||||
|
||||
const (
|
||||
domainIPv6 = "ipv6.only."
|
||||
domainSOA = "ipv4.soa."
|
||||
@@ -195,7 +162,7 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
|
||||
pt := testutil.NewPanicT(t)
|
||||
newUps := func(answers answerMap) (u upstream.Upstream) {
|
||||
return &testUpstream{
|
||||
return &dnsproxytest.Upstream{
|
||||
OnExchange: func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
q := req.Question[0]
|
||||
require.Contains(pt, answers, q.Qtype)
|
||||
@@ -214,8 +181,8 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
localRR := newRR(t, ptr64Domain, dns.TypePTR, 3600, domainPointed)
|
||||
localUps := &testUpstream{
|
||||
localRR := proxytest.NewRR(t, ptr64Domain, dns.TypePTR, 3600, domainPointed)
|
||||
localUps := &dnsproxytest.Upstream{
|
||||
OnExchange: func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
require.Equal(pt, req.Question[0].Name, ptr64Domain)
|
||||
resp = (&dns.Msg{}).SetReply(req)
|
||||
@@ -235,19 +202,20 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
qtype uint16
|
||||
}{{
|
||||
name: "simple_a",
|
||||
qname: ipv4OnlyFqdn,
|
||||
qname: proxytest.FQDN,
|
||||
upsAns: answerMap{
|
||||
dns.TypeA: {
|
||||
sectionAnswer: {newRR(t, ipv4OnlyFqdn, dns.TypeA, 3600, someIPv4)},
|
||||
sectionAnswer: {proxytest.NewRR(t, proxytest.FQDN, dns.TypeA, 3600, someIPv4)},
|
||||
},
|
||||
dns.TypeAAAA: {},
|
||||
},
|
||||
wantAns: []dns.RR{&dns.A{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: ipv4OnlyFqdn,
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Name: proxytest.FQDN,
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Rdlength: 4,
|
||||
},
|
||||
A: someIPv4,
|
||||
}},
|
||||
@@ -258,34 +226,36 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
upsAns: answerMap{
|
||||
dns.TypeA: {},
|
||||
dns.TypeAAAA: {
|
||||
sectionAnswer: {newRR(t, domainIPv6, dns.TypeAAAA, 3600, someIPv6)},
|
||||
sectionAnswer: {proxytest.NewRR(t, domainIPv6, dns.TypeAAAA, 3600, someIPv6)},
|
||||
},
|
||||
},
|
||||
wantAns: []dns.RR{&dns.AAAA{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: domainIPv6,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Name: domainIPv6,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Rdlength: 16,
|
||||
},
|
||||
AAAA: someIPv6,
|
||||
}},
|
||||
qtype: dns.TypeAAAA,
|
||||
}, {
|
||||
name: "actual_dns64",
|
||||
qname: ipv4OnlyFqdn,
|
||||
qname: proxytest.FQDN,
|
||||
upsAns: answerMap{
|
||||
dns.TypeA: {
|
||||
sectionAnswer: {newRR(t, ipv4OnlyFqdn, dns.TypeA, 3600, someIPv4)},
|
||||
sectionAnswer: {proxytest.NewRR(t, proxytest.FQDN, dns.TypeA, 3600, someIPv4)},
|
||||
},
|
||||
dns.TypeAAAA: {},
|
||||
},
|
||||
wantAns: []dns.RR{&dns.AAAA{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: ipv4OnlyFqdn,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: maxDNS64SynTTL,
|
||||
Name: proxytest.FQDN,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: testSynTTL,
|
||||
Rdlength: 16,
|
||||
},
|
||||
AAAA: mappedIPv6,
|
||||
}},
|
||||
@@ -295,18 +265,19 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
qname: domainSOA,
|
||||
upsAns: answerMap{
|
||||
dns.TypeA: {
|
||||
sectionAnswer: {newRR(t, domainSOA, dns.TypeA, 3600, someIPv4)},
|
||||
sectionAnswer: {proxytest.NewRR(t, domainSOA, dns.TypeA, 3600, someIPv4)},
|
||||
},
|
||||
dns.TypeAAAA: {
|
||||
sectionAuthority: {newRR(t, domainSOA, dns.TypeSOA, maxDNS64SynTTL+50, nil)},
|
||||
sectionAuthority: {proxytest.NewRR(t, domainSOA, dns.TypeSOA, testSynTTL+50, nil)},
|
||||
},
|
||||
},
|
||||
wantAns: []dns.RR{&dns.AAAA{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: domainSOA,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: maxDNS64SynTTL + 50,
|
||||
Name: domainSOA,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: testSynTTL + 50,
|
||||
Rdlength: 16,
|
||||
},
|
||||
AAAA: mappedIPv6,
|
||||
}},
|
||||
@@ -318,17 +289,18 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
dns.TypeA: {},
|
||||
dns.TypeAAAA: {
|
||||
sectionAnswer: {
|
||||
newRR(t, domainMapped, dns.TypeAAAA, 3600, net.ParseIP("64:ff9b::506:708")),
|
||||
newRR(t, domainMapped, dns.TypeCNAME, 3600, domainAnother),
|
||||
proxytest.NewRR(t, domainMapped, dns.TypeAAAA, 3600, filteredIPv6),
|
||||
proxytest.NewRR(t, domainMapped, dns.TypeCNAME, 3600, domainAnother),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantAns: []dns.RR{&dns.CNAME{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: domainMapped,
|
||||
Rrtype: dns.TypeCNAME,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Name: domainMapped,
|
||||
Rrtype: dns.TypeCNAME,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Rdlength: 16,
|
||||
},
|
||||
Target: domainAnother,
|
||||
}},
|
||||
@@ -339,10 +311,11 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
upsAns: nil,
|
||||
wantAns: []dns.RR{&dns.PTR{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: ptr64Domain,
|
||||
Rrtype: dns.TypePTR,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Name: ptr64Domain,
|
||||
Rrtype: dns.TypePTR,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Rdlength: 16,
|
||||
},
|
||||
Ptr: domainPointed,
|
||||
}},
|
||||
@@ -352,15 +325,16 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
qname: ptrGlobDomain,
|
||||
upsAns: answerMap{
|
||||
dns.TypePTR: {
|
||||
sectionAnswer: {newRR(t, ptrGlobDomain, dns.TypePTR, 3600, domainGlob)},
|
||||
sectionAnswer: {proxytest.NewRR(t, ptrGlobDomain, dns.TypePTR, 3600, domainGlob)},
|
||||
},
|
||||
},
|
||||
wantAns: []dns.RR{&dns.PTR{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: ptrGlobDomain,
|
||||
Rrtype: dns.TypePTR,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Name: ptrGlobDomain,
|
||||
Rrtype: dns.TypePTR,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Rdlength: 15,
|
||||
},
|
||||
Ptr: domainGlob,
|
||||
}},
|
||||
@@ -371,35 +345,37 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
upsAns: answerMap{
|
||||
dns.TypeA: {
|
||||
sectionAnswer: {
|
||||
newRR(t, fqdnCNAMEOnly, dns.TypeCNAME, 3600, fqdnTerminal),
|
||||
newRR(t, fqdnTerminal, dns.TypeA, 3600, someIPv4),
|
||||
proxytest.NewRR(t, fqdnCNAMEOnly, dns.TypeCNAME, 3600, fqdnTerminal),
|
||||
proxytest.NewRR(t, fqdnTerminal, dns.TypeA, 3600, someIPv4),
|
||||
},
|
||||
},
|
||||
dns.TypeAAAA: {
|
||||
sectionAnswer: {
|
||||
newRR(t, fqdnCNAMEOnly, dns.TypeCNAME, 3600, fqdnTerminal),
|
||||
proxytest.NewRR(t, fqdnCNAMEOnly, dns.TypeCNAME, 3600, fqdnTerminal),
|
||||
},
|
||||
sectionAuthority: {
|
||||
newRR(t, fqdnTerminal, dns.TypeSOA, 300, nil),
|
||||
proxytest.NewRR(t, fqdnTerminal, dns.TypeSOA, 300, nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantAns: []dns.RR{
|
||||
&dns.CNAME{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: fqdnCNAMEOnly,
|
||||
Rrtype: dns.TypeCNAME,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Name: fqdnCNAMEOnly,
|
||||
Rrtype: dns.TypeCNAME,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 3600,
|
||||
Rdlength: 15,
|
||||
},
|
||||
Target: fqdnTerminal,
|
||||
},
|
||||
&dns.AAAA{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: fqdnTerminal,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: maxDNS64SynTTL,
|
||||
Name: fqdnTerminal,
|
||||
Rrtype: dns.TypeAAAA,
|
||||
Class: dns.ClassINET,
|
||||
Ttl: testSynTTL,
|
||||
Rdlength: 16,
|
||||
},
|
||||
AAAA: mappedIPv6,
|
||||
},
|
||||
@@ -409,39 +385,42 @@ func TestProxy_Resolve_dns64(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
udpAddr := net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)
|
||||
tcpAddr := net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)
|
||||
udpAddr := net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)
|
||||
tcpAddr := net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)
|
||||
|
||||
p := mustNew(t, &Config{
|
||||
var p *proxy.Proxy
|
||||
p, err = proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{udpAddr},
|
||||
TCPListenAddr: []*net.TCPAddr{tcpAddr},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newUps(tc.upsAns)},
|
||||
},
|
||||
PrivateRDNSUpstreamConfig: &UpstreamConfig{
|
||||
PrivateRDNSUpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{localUps},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
CacheEnabled: true,
|
||||
|
||||
UseDNS64: true,
|
||||
UsePrivateRDNS: true,
|
||||
PrivateSubnets: netutil.SubnetSetFunc(netutil.IsLocallyServed),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
servicetest.RequireRun(t, p, proxytest.Timeout)
|
||||
|
||||
servicetest.RequireRun(t, p, dnsproxytest.Timeout)
|
||||
|
||||
dctx := &DNSContext{
|
||||
Req: (&dns.Msg{}).SetQuestion(tc.qname, tc.qtype),
|
||||
Addr: localCliAddr,
|
||||
}
|
||||
|
||||
err = p.handleDNSRequest(testutil.ContextWithTimeout(t, defaultTimeout), dctx)
|
||||
var conn *dns.Conn
|
||||
conn, err = dns.Dial("tcp", p.Addr(proxy.ProtoTCP).String())
|
||||
require.NoError(t, err)
|
||||
|
||||
res := dctx.Res
|
||||
err = conn.WriteMsg((&dns.Msg{}).SetQuestion(tc.qname, tc.qtype))
|
||||
require.NoError(t, err)
|
||||
|
||||
var res *dns.Msg
|
||||
res, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
|
||||
assert.Equal(t, tc.wantAns, res.Answer)
|
||||
})
|
||||
}
|
||||
@@ -214,8 +214,8 @@ func TestProxy_Exchange_loadBalance(t *testing.T) {
|
||||
|
||||
p := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: ups,
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/testutil/servicetest"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -43,10 +44,12 @@ func TestFilteringHandler(t *testing.T) {
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
RequestHandler: reqHandler,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
})
|
||||
|
||||
servicetest.RequireRun(t, dnsProxy, dnsproxytest.Timeout)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -18,8 +19,10 @@ func TestLookupNetIP(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
conf := &Config{
|
||||
Logger: testLogger,
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
Logger: testLogger,
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
}
|
||||
|
||||
p, err := New(conf)
|
||||
|
||||
+19
-270
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
glcache "github.com/AdguardTeam/golibs/cache"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/golibs/contextutil"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
@@ -67,15 +66,6 @@ func firstIP(resp *dns.Msg) (ip net.IP) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// newTestUpstreamConfig creates a new UpstreamConfig with given upstreams set.
|
||||
func newTestUpstreamConfig(tb testing.TB, ups ...upstream.Upstream) (u *UpstreamConfig) {
|
||||
tb.Helper()
|
||||
|
||||
return &UpstreamConfig{
|
||||
Upstreams: ups,
|
||||
}
|
||||
}
|
||||
|
||||
// newTestUpstream returns default upstream mock, which responds with single A
|
||||
// record with [dnsproxytest.IPv4] value to all requests. Other upstream
|
||||
// methods will be replaced with stub implementations.
|
||||
@@ -254,8 +244,8 @@ func TestProxy_Resolve_dnssecCache(t *testing.T) {
|
||||
|
||||
p := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{Upstreams: []upstream.Upstream{u}},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
CacheEnabled: true,
|
||||
@@ -345,257 +335,14 @@ func TestProxy_Resolve_dnssecCache(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_exchangeWithReservedDomains(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
emptyUpstream := newTestUpstreamWithExchange(
|
||||
t,
|
||||
func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return (&dns.Msg{}).SetReply(req), nil
|
||||
},
|
||||
)
|
||||
|
||||
const (
|
||||
host1 = "example-1.test"
|
||||
host2 = "test.example-1.test"
|
||||
|
||||
fqdn1 = host1 + "."
|
||||
fqdn2 = host2 + "."
|
||||
)
|
||||
|
||||
upsConf := &UpstreamConfig{
|
||||
DomainReservedUpstreams: map[string][]upstream.Upstream{
|
||||
fqdn1: {emptyUpstream},
|
||||
fqdn2: {},
|
||||
},
|
||||
SpecifiedDomainUpstreams: map[string][]upstream.Upstream{
|
||||
fqdn1: {emptyUpstream},
|
||||
fqdn2: {},
|
||||
},
|
||||
SubdomainExclusions: container.NewMapSet[string](),
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
}
|
||||
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: upsConf,
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
})
|
||||
|
||||
servicetest.RequireRun(t, dnsProxy, dnsproxytest.Timeout)
|
||||
|
||||
addr := dnsProxy.Addr(ProtoTCP)
|
||||
conn, err := dns.Dial("tcp", addr.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
var res *dns.Msg
|
||||
require.True(t, t.Run("common", func(t *testing.T) {
|
||||
req := dnsproxytest.NewTestRequest()
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
dnsproxytest.RequireResponse(t, req, res)
|
||||
}))
|
||||
|
||||
require.True(t, t.Run("empty_upstream_response", func(t *testing.T) {
|
||||
req := dnsproxytest.NewTestRequestWithHost(host1)
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, res.Answer)
|
||||
}))
|
||||
|
||||
require.True(t, t.Run("non_empty_response_for_subdomain", func(t *testing.T) {
|
||||
req := dnsproxytest.NewTestRequestWithHost(host2)
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
dnsproxytest.RequireResponse(t, req, res)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_oneByOneUpstreamsExchange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
errUpstream := newTestUpstreamWithExchange(
|
||||
t,
|
||||
func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return nil, assert.AnError
|
||||
},
|
||||
)
|
||||
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: newTestUpstreamConfig(
|
||||
t,
|
||||
errUpstream,
|
||||
errUpstream,
|
||||
newTestUpstream(t),
|
||||
),
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
Fallbacks: newTestUpstreamConfig(t, errUpstream),
|
||||
})
|
||||
|
||||
servicetest.RequireRun(t, dnsProxy, dnsproxytest.Timeout)
|
||||
|
||||
addr := dnsProxy.Addr(ProtoTCP)
|
||||
conn, err := dns.Dial("tcp", addr.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
req := dnsproxytest.NewTestRequest()
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
start := time.Now()
|
||||
res, err := conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
dnsproxytest.RequireResponse(t, req, res)
|
||||
|
||||
elapsed := time.Since(start)
|
||||
assert.Greater(t, 3*dnsproxytest.Timeout, elapsed)
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_fallback(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
hostSuccess = "specific.example"
|
||||
hostFail = "failing.example"
|
||||
hostFallbackSuccess = "fallback.success.example"
|
||||
|
||||
fqdnSuccess = hostSuccess + "."
|
||||
fqdnFail = hostFail + "."
|
||||
fqdnFallbackSuccess = hostFallbackSuccess + "."
|
||||
)
|
||||
|
||||
responseCh := make(chan uint16)
|
||||
failCh := make(chan uint16)
|
||||
|
||||
pt := testutil.NewPanicT(t)
|
||||
|
||||
successExchange := func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
testutil.RequireSend(pt, responseCh, req.Id, dnsproxytest.Timeout)
|
||||
|
||||
return dnsproxytest.NewTestResponse(req), nil
|
||||
}
|
||||
successUpstream := newTestUpstreamWithExchange(t, successExchange)
|
||||
|
||||
failUpstream := newTestUpstreamWithExchange(
|
||||
t,
|
||||
func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
testutil.RequireSend(pt, failCh, req.Id, dnsproxytest.Timeout)
|
||||
|
||||
return nil, assert.AnError
|
||||
},
|
||||
)
|
||||
|
||||
upsConf := &UpstreamConfig{
|
||||
DomainReservedUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnSuccess: {successUpstream},
|
||||
fqdnFail: {failUpstream},
|
||||
},
|
||||
SpecifiedDomainUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnSuccess: {successUpstream},
|
||||
fqdnFail: {failUpstream},
|
||||
},
|
||||
|
||||
SubdomainExclusions: container.NewMapSet[string](),
|
||||
Upstreams: []upstream.Upstream{failUpstream},
|
||||
}
|
||||
|
||||
fallbackConf := &UpstreamConfig{
|
||||
DomainReservedUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnFail: {failUpstream},
|
||||
fqdnFallbackSuccess: {successUpstream},
|
||||
},
|
||||
SpecifiedDomainUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnFail: {failUpstream},
|
||||
fqdnFallbackSuccess: {successUpstream},
|
||||
},
|
||||
|
||||
SubdomainExclusions: container.NewMapSet[string](),
|
||||
Upstreams: []upstream.Upstream{failUpstream, successUpstream},
|
||||
}
|
||||
|
||||
dnsProxy := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: upsConf,
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
Fallbacks: fallbackConf,
|
||||
})
|
||||
|
||||
servicetest.RequireRun(t, dnsProxy, dnsproxytest.Timeout)
|
||||
|
||||
conn, err := dns.Dial("tcp", dnsProxy.Addr(ProtoTCP).String())
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
wantSignals []chan uint16
|
||||
}{{
|
||||
name: dnsproxytest.Host,
|
||||
wantSignals: []chan uint16{
|
||||
failCh,
|
||||
// Both non-specific fallbacks tried.
|
||||
failCh,
|
||||
responseCh,
|
||||
},
|
||||
}, {
|
||||
name: hostSuccess,
|
||||
wantSignals: []chan uint16{
|
||||
responseCh,
|
||||
},
|
||||
}, {
|
||||
name: hostFail,
|
||||
wantSignals: []chan uint16{
|
||||
failCh,
|
||||
failCh,
|
||||
},
|
||||
}, {
|
||||
name: hostFallbackSuccess,
|
||||
wantSignals: []chan uint16{
|
||||
failCh,
|
||||
responseCh,
|
||||
},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := dnsproxytest.NewTestRequestWithHost(tc.name)
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, ch := range tc.wantSignals {
|
||||
reqID, ok := testutil.RequireReceive(testutil.NewPanicT(t), ch, dnsproxytest.Timeout)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, req.Id, reqID)
|
||||
}
|
||||
|
||||
_, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_Resolve_exchangeCustomUpstreamConfig(t *testing.T) {
|
||||
p := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
})
|
||||
|
||||
@@ -632,10 +379,12 @@ func TestProxy_Resolve_exchangeCustomUpstreamConfig(t *testing.T) {
|
||||
|
||||
func TestProxy_Resolve_customUpstreamConfigCache(t *testing.T) {
|
||||
prx := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
CacheEnabled: true,
|
||||
DNSSECEnabled: true,
|
||||
@@ -767,8 +516,8 @@ func TestProxy_Resolve_ecs(t *testing.T) {
|
||||
|
||||
prx := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TCPListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{u},
|
||||
},
|
||||
@@ -887,8 +636,8 @@ func TestProxy_Resolve_ecsProxyCacheMinMaxTTL(t *testing.T) {
|
||||
}}
|
||||
ecsIP = clientIP
|
||||
|
||||
udpAddr := net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)
|
||||
tcpAddr := net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)
|
||||
udpAddr := dnsproxytest.LocalhostAnyPortUDP
|
||||
tcpAddr := dnsproxytest.LocalhostAnyPortTCP
|
||||
|
||||
prx := mustNew(t, &Config{
|
||||
Logger: testLogger,
|
||||
@@ -1098,7 +847,7 @@ func TestProxy_ValidateRequest(t *testing.T) {
|
||||
|
||||
p, err := New(&Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
UDPListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
UpstreamConfig: &UpstreamConfig{Upstreams: []upstream.Upstream{ups}},
|
||||
RefuseAny: true,
|
||||
PrivateSubnets: privateNets,
|
||||
|
||||
+279
-21
@@ -15,6 +15,7 @@ import (
|
||||
proxytest "github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/golibs/testutil/servicetest"
|
||||
@@ -39,30 +40,35 @@ var (
|
||||
testIPv4 = net.IP{192, 0, 2, 0}
|
||||
)
|
||||
|
||||
// newTestUpstreamConfig creates a new upstream config with the default mock
|
||||
// upstream, which expects the request will contain a single question with the
|
||||
// [proxytest.Host] name.
|
||||
//
|
||||
// TODO(f.setrakov): DRY with internal version.
|
||||
func newTestUpstreamConfig(tb testing.TB) (uc *proxy.UpstreamConfig) {
|
||||
// TODO(f.setrakov): DRY upstream helpers with their internal versions.
|
||||
|
||||
// newTestUpstream returns default upstream mock, which responds with single A
|
||||
// record with [proxytest.IPv4] value to all requests. Other upstream
|
||||
// methods will be replaced with stub implementations.
|
||||
func newTestUpstream(tb testing.TB) (uc upstream.Upstream) {
|
||||
tb.Helper()
|
||||
|
||||
onExchange := func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
pt := testutil.NewPanicT(tb)
|
||||
|
||||
require.Len(pt, req.Question, 1)
|
||||
assert.Equal(pt, dns.Fqdn(proxytest.Host), req.Question[0].Name)
|
||||
|
||||
return proxytest.NewTestResponse(req), nil
|
||||
}
|
||||
|
||||
u := &dnsproxytest.Upstream{
|
||||
return newTestUpstreamWithExchange(tb, onExchange)
|
||||
}
|
||||
|
||||
// newTestUpstreamWithExchange returns upstream mock which uses given callback
|
||||
// for [upstream.Upstream.Exchange] implementation. Other upstream methods will
|
||||
// be replaced with stub implementations.
|
||||
func newTestUpstreamWithExchange(
|
||||
tb testing.TB,
|
||||
onExchange func(ctx context.Context, req *dns.Msg) (resp *dns.Msg, err error),
|
||||
) (uc upstream.Upstream) {
|
||||
tb.Helper()
|
||||
|
||||
return &dnsproxytest.Upstream{
|
||||
OnAddress: func() (addr string) { return "" },
|
||||
OnExchange: onExchange,
|
||||
OnClose: func() (err error) { return nil },
|
||||
}
|
||||
|
||||
return &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{u},
|
||||
}
|
||||
}
|
||||
|
||||
// mustStartDefaultProxy starts a new proxy with default settings and returns
|
||||
@@ -71,10 +77,12 @@ func mustStartDefaultProxy(tb testing.TB) (p *proxy.Proxy) {
|
||||
tb.Helper()
|
||||
|
||||
p, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: newTestUpstreamConfig(tb),
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(tb)},
|
||||
},
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
})
|
||||
require.NoError(tb, err)
|
||||
@@ -186,7 +194,9 @@ func isCachedWithCustomConfig(
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_race(t *testing.T) {
|
||||
upsConf := newTestUpstreamConfig(t)
|
||||
upsConf := &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
}
|
||||
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
@@ -487,3 +497,251 @@ func requireReadPacket(tb testing.TB, conn net.Conn) (data []byte) {
|
||||
|
||||
return buf[:n]
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_exchangeWithReservedDomains(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
emptyUpstream := newTestUpstreamWithExchange(
|
||||
t,
|
||||
func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return (&dns.Msg{}).SetReply(req), nil
|
||||
},
|
||||
)
|
||||
|
||||
const (
|
||||
host1 = "test-1.example"
|
||||
host2 = "subdomain." + host1
|
||||
|
||||
fqdn1 = host1 + "."
|
||||
fqdn2 = host2 + "."
|
||||
)
|
||||
|
||||
upsConf := &proxy.UpstreamConfig{
|
||||
DomainReservedUpstreams: map[string][]upstream.Upstream{
|
||||
fqdn1: {emptyUpstream},
|
||||
fqdn2: {},
|
||||
},
|
||||
SpecifiedDomainUpstreams: map[string][]upstream.Upstream{
|
||||
fqdn1: {emptyUpstream},
|
||||
fqdn2: {},
|
||||
},
|
||||
SubdomainExclusions: container.NewMapSet[string](),
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
}
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: upsConf,
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
servicetest.RequireRun(t, dnsProxy, proxytest.Timeout)
|
||||
|
||||
addr := dnsProxy.Addr(proxy.ProtoTCP)
|
||||
conn, err := dns.Dial("tcp", addr.String())
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, conn.Close)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
host string
|
||||
wantResponse bool
|
||||
}{{
|
||||
name: "common",
|
||||
host: proxytest.Host,
|
||||
wantResponse: true,
|
||||
}, {
|
||||
name: "empty_upstream_response",
|
||||
host: host1,
|
||||
wantResponse: false,
|
||||
}, {
|
||||
name: "non_empty_response_for_subdomain",
|
||||
host: host2,
|
||||
wantResponse: true,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := proxytest.NewTestRequestWithHost(tc.host)
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
var res *dns.Msg
|
||||
res, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.wantResponse {
|
||||
proxytest.RequireResponse(t, req, res)
|
||||
} else {
|
||||
require.NotNil(t, res)
|
||||
require.Empty(t, res.Answer)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_oneByOneUpstreamsExchange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
errUpstream := newTestUpstreamWithExchange(
|
||||
t,
|
||||
func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
return nil, assert.AnError
|
||||
},
|
||||
)
|
||||
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{errUpstream, errUpstream, newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
Fallbacks: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{errUpstream},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
servicetest.RequireRun(t, dnsProxy, proxytest.Timeout)
|
||||
|
||||
addr := dnsProxy.Addr(proxy.ProtoTCP)
|
||||
conn, err := dns.Dial("tcp", addr.String())
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, conn.Close)
|
||||
|
||||
req := proxytest.NewTestRequest()
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
proxytest.RequireResponse(t, req, res)
|
||||
}
|
||||
|
||||
func TestProxy_HandleDNSRequest_fallback(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
hostSuccess = "specific.example"
|
||||
hostFail = "failing.example"
|
||||
hostFallbackSuccess = "fallback.success.example"
|
||||
|
||||
fqdnSuccess = hostSuccess + "."
|
||||
fqdnFail = hostFail + "."
|
||||
fqdnFallbackSuccess = hostFallbackSuccess + "."
|
||||
)
|
||||
|
||||
responseCh := make(chan uint16)
|
||||
failCh := make(chan uint16)
|
||||
|
||||
pt := testutil.NewPanicT(t)
|
||||
|
||||
successExchange := func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
testutil.RequireSend(pt, responseCh, req.Id, proxytest.Timeout)
|
||||
|
||||
return proxytest.NewTestResponse(req), nil
|
||||
}
|
||||
successUpstream := newTestUpstreamWithExchange(t, successExchange)
|
||||
|
||||
failUpstream := newTestUpstreamWithExchange(
|
||||
t,
|
||||
func(_ context.Context, req *dns.Msg) (resp *dns.Msg, err error) {
|
||||
testutil.RequireSend(pt, failCh, req.Id, proxytest.Timeout)
|
||||
|
||||
return nil, assert.AnError
|
||||
},
|
||||
)
|
||||
|
||||
upsConf := &proxy.UpstreamConfig{
|
||||
DomainReservedUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnSuccess: {successUpstream},
|
||||
fqdnFail: {failUpstream},
|
||||
},
|
||||
SpecifiedDomainUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnSuccess: {successUpstream},
|
||||
fqdnFail: {failUpstream},
|
||||
},
|
||||
|
||||
SubdomainExclusions: container.NewMapSet[string](),
|
||||
Upstreams: []upstream.Upstream{failUpstream},
|
||||
}
|
||||
|
||||
fallbackConf := &proxy.UpstreamConfig{
|
||||
DomainReservedUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnFail: {failUpstream},
|
||||
fqdnFallbackSuccess: {successUpstream},
|
||||
},
|
||||
SpecifiedDomainUpstreams: map[string][]upstream.Upstream{
|
||||
fqdnFail: {failUpstream},
|
||||
fqdnFallbackSuccess: {successUpstream},
|
||||
},
|
||||
|
||||
SubdomainExclusions: container.NewMapSet[string](),
|
||||
Upstreams: []upstream.Upstream{failUpstream, successUpstream},
|
||||
}
|
||||
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
UpstreamConfig: upsConf,
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
Fallbacks: fallbackConf,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
servicetest.RequireRun(t, dnsProxy, proxytest.Timeout)
|
||||
|
||||
conn, err := dns.Dial("tcp", dnsProxy.Addr(proxy.ProtoTCP).String())
|
||||
require.NoError(t, err)
|
||||
testutil.CleanupAndRequireSuccess(t, conn.Close)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
wantSignals []chan uint16
|
||||
}{{
|
||||
name: proxytest.Host,
|
||||
wantSignals: []chan uint16{
|
||||
failCh,
|
||||
failCh,
|
||||
responseCh,
|
||||
},
|
||||
}, {
|
||||
name: hostSuccess,
|
||||
wantSignals: []chan uint16{
|
||||
responseCh,
|
||||
},
|
||||
}, {
|
||||
name: hostFail,
|
||||
wantSignals: []chan uint16{
|
||||
failCh,
|
||||
failCh,
|
||||
},
|
||||
}, {
|
||||
name: hostFallbackSuccess,
|
||||
wantSignals: []chan uint16{
|
||||
failCh,
|
||||
responseCh,
|
||||
},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := proxytest.NewTestRequestWithHost(tc.name)
|
||||
err = conn.WriteMsg(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, ch := range tc.wantSignals {
|
||||
reqID, ok := testutil.RequireReceive(testutil.NewPanicT(t), ch, proxytest.Timeout)
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, req.Id, reqID)
|
||||
}
|
||||
|
||||
_, err = conn.ReadMsg()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/AdguardTeam/dnscrypt"
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/internal/nettest"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
@@ -54,7 +55,9 @@ func newTestDNSCryptProxy(tb testing.TB) (p *Proxy, rc dnscrypt.ResolverConfig)
|
||||
DNSCryptTCPListenAddr: []*net.TCPAddr{{
|
||||
Port: int(port), IP: net.ParseIP(listenIP),
|
||||
}},
|
||||
UpstreamConfig: newTestUpstreamConfig(tb, newTestUpstream(tb)),
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(tb)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
EnableEDNSClientSubnet: true,
|
||||
CacheEnabled: true,
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
proxytest "github.com/AdguardTeam/dnsproxy/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/httphdr"
|
||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
@@ -68,14 +69,16 @@ func TestProxy_HandleDNSRequest_https(t *testing.T) {
|
||||
HTTP3Enabled: tc.http3,
|
||||
}
|
||||
|
||||
tlsListenAddr := net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)
|
||||
quicListenAddr := net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)
|
||||
tlsListenAddr := dnsproxytest.LocalhostAnyPortTCP
|
||||
quicListenAddr := dnsproxytest.LocalhostAnyPortUDP
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
TLSListenAddr: []*net.TCPAddr{tlsListenAddr},
|
||||
QUICListenAddr: []*net.UDPAddr{quicListenAddr},
|
||||
TLSConfig: tlsConf,
|
||||
UpstreamConfig: newTestUpstreamConfig(t),
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
HTTPConfig: httpConf,
|
||||
})
|
||||
@@ -150,13 +153,15 @@ func testProxyRealIPDetection(
|
||||
}
|
||||
trustedProxies := netip.PrefixFrom(trustedProxy, trustedProxy.BitLen())
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UpstreamConfig: newTestUpstreamConfig(tb),
|
||||
Logger: testLogger,
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(tb)},
|
||||
},
|
||||
TrustedProxies: trustedProxies,
|
||||
RequestHandler: reqHandler,
|
||||
TLSConfig: tlsConf,
|
||||
TLSListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
QUICListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TLSListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
QUICListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
HTTPConfig: httpConf,
|
||||
})
|
||||
require.NoError(tb, err)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/proxyutil"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/syncutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/golibs/testutil/servicetest"
|
||||
@@ -26,9 +27,11 @@ func TestProxy_HandleDNSRequest_quicTruncatedRequest(t *testing.T) {
|
||||
|
||||
conf := &Config{
|
||||
Logger: testLogger,
|
||||
QUICListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
QUICListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TLSConfig: serverConfig,
|
||||
UpstreamConfig: newTestUpstreamConfig(t, newTestUpstream(t)),
|
||||
UpstreamConfig: &UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
RequestHandler: &testHandler{
|
||||
OnHandle: func(ctx context.Context, p *Proxy, d *DNSContext) (_ error) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/proxyutil"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/golibs/testutil/servicetest"
|
||||
"github.com/miekg/dns"
|
||||
@@ -51,9 +52,11 @@ func TestProxy_HandleDNSRequest_quic(t *testing.T) {
|
||||
|
||||
conf := &proxy.Config{
|
||||
Logger: testLogger,
|
||||
QUICListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
QUICListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
TLSConfig: serverConfig,
|
||||
UpstreamConfig: newTestUpstreamConfig(t),
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
}
|
||||
|
||||
@@ -64,7 +67,9 @@ func TestProxy_HandleDNSRequest_quic(t *testing.T) {
|
||||
require.False(t, t.Failed())
|
||||
|
||||
conf.QUICListenAddr = []*net.UDPAddr{addr}
|
||||
conf.UpstreamConfig = newTestUpstreamConfig(t)
|
||||
conf.UpstreamConfig = &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
}
|
||||
|
||||
require.True(t, t.Run("rerun", func(t *testing.T) {
|
||||
testHandleDNSRequestQUIC(t, conf, tlsConfig)
|
||||
@@ -115,13 +120,15 @@ func TestProxy_HandleDNSRequest_quicLargePackets(t *testing.T) {
|
||||
|
||||
serverConfig, caPem := dnsproxytest.NewTLSConfig(t)
|
||||
dnsProxy, err := proxy.New(&proxy.Config{
|
||||
Logger: testLogger,
|
||||
UpstreamConfig: newTestUpstreamConfig(t),
|
||||
Logger: testLogger,
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: dnsproxytest.DefaultTrustedProxies,
|
||||
RequestHandler: reqHandler,
|
||||
TLSConfig: serverConfig,
|
||||
TLSListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
QUICListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(dnsproxytest.LocalhostAnyPort)},
|
||||
TLSListenAddr: []*net.TCPAddr{dnsproxytest.LocalhostAnyPortTCP},
|
||||
QUICListenAddr: []*net.UDPAddr{dnsproxytest.LocalhostAnyPortUDP},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ func TestProxy_HandleDNSRequest_tls(t *testing.T) {
|
||||
TLSListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
QUICListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(proxytest.LocalhostAnyPort)},
|
||||
TLSConfig: serverConfig,
|
||||
UpstreamConfig: newTestUpstreamConfig(t),
|
||||
UpstreamConfig: &proxy.UpstreamConfig{
|
||||
Upstreams: []upstream.Upstream{newTestUpstream(t)},
|
||||
},
|
||||
TrustedProxies: proxytest.DefaultTrustedProxies,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user