Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion proxy/cache_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ func TestServeCached(t *testing.T) {
dnsProxy.cache.set(reply, upstreamWithAddr, testLogger)

// Create a DNS-over-UDP client connection.
addr := dnsProxy.Addr(ProtoUDP)
addr, err := dnsProxy.Addr(ProtoUDP)
require.NoError(t, err)

client := &dns.Client{
Net: string(ProtoUDP),
Timeout: testTimeout,
Expand Down
6 changes: 4 additions & 2 deletions proxy/dns64_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ func TestDNS64Race(t *testing.T) {
g := &sync.WaitGroup{}
g.Add(testMessagesCount)

addr := dnsProxy.Addr(ProtoTCP).String()
addr, err := dnsProxy.Addr(ProtoTCP)
require.NoError(t, err)

for range testMessagesCount {
// The [dns.Conn] isn't safe for concurrent use despite the requirements
// from the [net.Conn] documentation.
conn, err := dns.Dial("tcp", addr)
conn, err := dns.Dial("tcp", addr.String())
require.NoError(t, err)

go sendTestAAAAMessageAsync(conn, g, ipv4OnlyFqdn, syncCh)
Expand Down
4 changes: 3 additions & 1 deletion proxy/handler_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ func TestFilteringHandler(t *testing.T) {
servicetest.RequireRun(t, dnsProxy, testTimeout)

// Create a DNS-over-UDP client connection
addr := dnsProxy.Addr(ProtoUDP)
addr, err := dnsProxy.Addr(ProtoUDP)
require.NoError(t, err)

client := &dns.Client{
Net: string(ProtoUDP),
Timeout: testTimeout,
Expand Down
6 changes: 4 additions & 2 deletions proxy/pending_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ func TestPendingRequests(t *testing.T) {

servicetest.RequireRun(t, p, testTimeout)

addr := p.Addr(proxy.ProtoTCP).String()
addr, err := p.Addr(proxy.ProtoTCP)
require.NoError(t, err)

client := &dns.Client{
Net: string(proxy.ProtoTCP),
Timeout: testTimeout,
Expand All @@ -142,7 +144,7 @@ func TestPendingRequests(t *testing.T) {
defer resolveWG.Done()

reqCtx := testutil.ContextWithTimeout(t, testTimeout)
responses[i], _, errs[i] = client.ExchangeContext(reqCtx, req, addr)
responses[i], _, errs[i] = client.ExchangeContext(reqCtx, req, addr.String())
}()
}

Expand Down
33 changes: 16 additions & 17 deletions proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,32 +479,31 @@ func collectAddrs[A any](listeners []A, af addrFunc[A]) (addrs []net.Addr) {
// Addrs returns all listen addresses for the specified proto or nil if the
// proxy does not listen to it. proto must be one of [Proto]: [ProtoTCP],
// [ProtoUDP], [ProtoTLS], [ProtoHTTPS], [ProtoQUIC], or [ProtoDNSCrypt].
func (p *Proxy) Addrs(proto Proto) (addrs []net.Addr) {
func (p *Proxy) Addrs(proto Proto) (addrs []net.Addr, err error) {
p.RLock()
defer p.RUnlock()

switch proto {
case ProtoTCP:
return collectAddrs(p.tcpListen, net.Listener.Addr)
return collectAddrs(p.tcpListen, net.Listener.Addr), nil
case ProtoTLS:
return collectAddrs(p.tlsListen, net.Listener.Addr)
return collectAddrs(p.tlsListen, net.Listener.Addr), nil
case ProtoHTTPS:
return collectAddrs(p.httpsListen, net.Listener.Addr)
return collectAddrs(p.httpsListen, net.Listener.Addr), nil
case ProtoUDP:
return collectAddrs(p.udpListen, (*net.UDPConn).LocalAddr)
return collectAddrs(p.udpListen, (*net.UDPConn).LocalAddr), nil
case ProtoQUIC:
return collectAddrs(p.quicListen, (*quic.EarlyListener).Addr)
return collectAddrs(p.quicListen, (*quic.EarlyListener).Addr), nil
case ProtoDNSCrypt:
// Using only UDP addrs here
//
// TODO(ameshkov): To do it better we should either do
// ProtoDNSCryptTCP/ProtoDNSCryptUDP or we should change the
// configuration so that it was not possible to set different ports for
// TCP/UDP listeners.
return collectAddrs(p.dnsCryptUDPListen, (*net.UDPConn).LocalAddr)
return collectAddrs(p.dnsCryptUDPListen, (*net.UDPConn).LocalAddr), nil
default:
// TODO(e.burkov): Use [errors.ErrBadEnumValue].
panic("proto must be 'tcp', 'tls', 'https', 'quic', 'dnscrypt' or 'udp'")
return nil, fmt.Errorf("proto: %w: %q", errors.ErrBadEnumValue, proto)
}
}

Expand All @@ -521,25 +520,25 @@ func firstAddr[A any](listeners []A, af addrFunc[A]) (addr net.Addr) {
// Addr returns the first listen address for the specified proto or nil if the
// proxy does not listen to it. proto must be one of [Proto]: [ProtoTCP],
// [ProtoUDP], [ProtoTLS], [ProtoHTTPS], [ProtoQUIC], or [ProtoDNSCrypt].
func (p *Proxy) Addr(proto Proto) (addr net.Addr) {
func (p *Proxy) Addr(proto Proto) (addr net.Addr, err error) {
p.RLock()
defer p.RUnlock()

switch proto {
case ProtoTCP:
return firstAddr(p.tcpListen, net.Listener.Addr)
return firstAddr(p.tcpListen, net.Listener.Addr), nil
case ProtoTLS:
return firstAddr(p.tlsListen, net.Listener.Addr)
return firstAddr(p.tlsListen, net.Listener.Addr), nil
case ProtoHTTPS:
return firstAddr(p.httpsListen, net.Listener.Addr)
return firstAddr(p.httpsListen, net.Listener.Addr), nil
case ProtoUDP:
return firstAddr(p.udpListen, (*net.UDPConn).LocalAddr)
return firstAddr(p.udpListen, (*net.UDPConn).LocalAddr), nil
case ProtoQUIC:
return firstAddr(p.quicListen, (*quic.EarlyListener).Addr)
return firstAddr(p.quicListen, (*quic.EarlyListener).Addr), nil
case ProtoDNSCrypt:
return firstAddr(p.dnsCryptUDPListen, (*net.UDPConn).LocalAddr)
return firstAddr(p.dnsCryptUDPListen, (*net.UDPConn).LocalAddr), nil
default:
panic("proto must be 'tcp', 'tls', 'https', 'quic', 'dnscrypt' or 'udp'")
return nil, fmt.Errorf("proto: %w: %q", errors.ErrBadEnumValue, proto)
}
}

Expand Down
44 changes: 38 additions & 6 deletions proxy/proxy_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
"github.com/AdguardTeam/dnsproxy/upstream"
glcache "github.com/AdguardTeam/golibs/cache"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/testutil"
Expand Down Expand Up @@ -313,7 +314,9 @@ func TestProxyRace(t *testing.T) {
servicetest.RequireRun(t, dnsProxy, testTimeout)

// Create a DNS-over-UDP client connection
addr := dnsProxy.Addr(ProtoUDP)
addr, err := dnsProxy.Addr(ProtoUDP)
require.NoError(t, err)

conn, err := dns.Dial("udp", addr.String())
require.NoError(t, err)

Expand Down Expand Up @@ -610,7 +613,9 @@ func TestExchangeWithReservedDomains(t *testing.T) {
servicetest.RequireRun(t, dnsProxy, testTimeout)

// Create a DNS-over-TCP client connection.
addr := dnsProxy.Addr(ProtoTCP)
addr, err := dnsProxy.Addr(ProtoTCP)
require.NoError(t, err)

conn, err := dns.Dial("tcp", addr.String())
require.NoError(t, err)

Expand Down Expand Up @@ -675,7 +680,9 @@ func TestOneByOneUpstreamsExchange(t *testing.T) {
servicetest.RequireRun(t, dnsProxy, testTimeout)

// create a DNS-over-TCP client connection
addr := dnsProxy.Addr(ProtoTCP)
addr, err := dnsProxy.Addr(ProtoTCP)
require.NoError(t, err)

conn, err := dns.Dial("tcp", addr.String())
require.NoError(t, err)

Expand Down Expand Up @@ -771,7 +778,10 @@ func TestFallback(t *testing.T) {

servicetest.RequireRun(t, dnsProxy, testTimeout)

conn, err := dns.Dial("tcp", dnsProxy.Addr(ProtoTCP).String())
addr, err := dnsProxy.Addr(ProtoTCP)
require.NoError(t, err)

conn, err := dns.Dial("tcp", addr.String())
require.NoError(t, err)

testCases := []struct {
Expand Down Expand Up @@ -856,7 +866,9 @@ func TestFallbackFromInvalidBootstrap(t *testing.T) {
servicetest.RequireRun(t, dnsProxy, testTimeout)

// Create a DNS-over-UDP client connection
addr := dnsProxy.Addr(ProtoUDP)
addr, err := dnsProxy.Addr(ProtoUDP)
require.NoError(t, err)

conn, err := dns.Dial("udp", addr.String())
require.NoError(t, err)

Expand All @@ -878,7 +890,9 @@ func TestFallbackFromInvalidBootstrap(t *testing.T) {
func TestResponseInRequest(t *testing.T) {
dnsProxy := mustStartDefaultProxy(t)

addr := dnsProxy.Addr(ProtoUDP)
addr, err := dnsProxy.Addr(ProtoUDP)
require.NoError(t, err)

client := &dns.Client{
Net: string(ProtoUDP),
Timeout: testTimeout,
Expand Down Expand Up @@ -1508,3 +1522,21 @@ func TestProxy_validateRequest(t *testing.T) {
})
}
}

func TestProxy_Addr_InvalidProto(t *testing.T) {
t.Parallel()

p := &Proxy{}
_, err := p.Addr(Proto("invalid"))
require.Error(t, err)
require.ErrorIs(t, err, errors.ErrBadEnumValue)
}

func TestProxy_Addrs_InvalidProto(t *testing.T) {
t.Parallel()

p := &Proxy{}
_, err := p.Addrs(Proto("invalid"))
require.Error(t, err)
require.ErrorIs(t, err, errors.ErrBadEnumValue)
}
6 changes: 5 additions & 1 deletion proxy/serverdnscrypt_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ameshkov/dnscrypt/v2"
"github.com/ameshkov/dnsstamps"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// TODO(d.kolyshev): Remove this after quic-go has migrated to slog.
Expand Down Expand Up @@ -66,7 +67,10 @@ func TestDNSCryptProxy(t *testing.T) {
servicetest.RequireRun(t, dnsProxy, testTimeout)

// Generate a DNS stamp
port := testutil.RequireTypeAssert[*net.UDPAddr](t, dnsProxy.Addr(ProtoDNSCrypt)).Port
addrProto, err := dnsProxy.Addr(ProtoDNSCrypt)
require.NoError(t, err)

port := testutil.RequireTypeAssert[*net.UDPAddr](t, addrProto).Port
addr := netutil.JoinHostPort(listenIP, uint16(port))
stamp, err := rc.CreateStamp(addr)
assert.Nil(t, err)
Expand Down
15 changes: 12 additions & 3 deletions proxy/serverhttps_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,12 @@ func createTestHTTPClient(dnsProxy *Proxy, caPem []byte, http3Enabled bool) (cli
tlsCfg *tls.Config,
cfg *quic.Config,
) (*quic.Conn, error) {
addr := dnsProxy.Addr(ProtoHTTPS).String()
return quic.DialAddrEarly(ctx, addr, tlsCfg, cfg)
addr, err := dnsProxy.Addr(ProtoHTTPS)
if err != nil {
return nil, err
}

return quic.DialAddrEarly(ctx, addr.String(), tlsCfg, cfg)
},
TLSClientConfig: tlsClientConfig,
QUICConfig: &quic.Config{},
Expand All @@ -448,7 +452,12 @@ func createTestHTTPClient(dnsProxy *Proxy, caPem []byte, http3Enabled bool) (cli
}
dialContext := func(ctx context.Context, network, addr string) (net.Conn, error) {
// Route request to the DNS-over-HTTPS server address.
return dialer.DialContext(ctx, network, dnsProxy.Addr(ProtoHTTPS).String())
hAddr, err := dnsProxy.Addr(ProtoHTTPS)
if err != nil {
return nil, err
}

return dialer.DialContext(ctx, network, hAddr.String())
}

tlsClientConfig.NextProtos = []string{"h2", "http/1.1"}
Expand Down
11 changes: 8 additions & 3 deletions proxy/serverquic_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ func TestProxy_quic(t *testing.T) {

servicetest.RequireRun(t, dnsProxy, testTimeout)

addr = testutil.RequireTypeAssert[*net.UDPAddr](t, dnsProxy.Addr(ProtoQUIC))
addrProto, err := dnsProxy.Addr(ProtoQUIC)
require.NoError(t, err)

addr = testutil.RequireTypeAssert[*net.UDPAddr](t, addrProto)

conn, err := quic.DialAddrEarly(context.Background(), addr.String(), tlsConfig, nil)
require.NoError(t, err)
Expand Down Expand Up @@ -113,7 +116,8 @@ func TestProxy_quicLargePackets(t *testing.T) {
}

// Create a DNS-over-QUIC client connection.
addr := dnsProxy.Addr(ProtoQUIC)
addr, err := dnsProxy.Addr(ProtoQUIC)
require.NoError(t, err)

// Open a QUIC connection.
conn, err := quic.DialAddrEarly(context.Background(), addr.String(), tlsConfig, nil)
Expand Down Expand Up @@ -181,7 +185,8 @@ func TestProxy_quicTruncatedRequest(t *testing.T) {

servicetest.RequireRun(t, dnsProxy, testTimeout)

addr := dnsProxy.Addr(ProtoQUIC)
addr, err := dnsProxy.Addr(ProtoQUIC)
require.NoError(t, err)

roots := x509.NewCertPool()
require.True(t, roots.AppendCertsFromPEM(caPem))
Expand Down
8 changes: 6 additions & 2 deletions proxy/servertcp_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ func TestProxy_tcp(t *testing.T) {
dnsProxy := mustStartDefaultProxy(t)

// Create a DNS-over-TCP client connection
addr := dnsProxy.Addr(ProtoTCP)
addr, err := dnsProxy.Addr(ProtoTCP)
require.NoError(t, err)

conn, err := dns.Dial("tcp", addr.String())
require.NoError(t, err)

Expand All @@ -40,7 +42,9 @@ func TestProxy_tls(t *testing.T) {
tlsConfig := &tls.Config{ServerName: tlsServerName, RootCAs: roots}

// Create a DNS-over-TLS client connection
addr := dnsProxy.Addr(ProtoTLS)
addr, err := dnsProxy.Addr(ProtoTLS)
require.NoError(t, err)

conn, err := dns.DialWithTLS("tcp-tls", addr.String(), tlsConfig)
require.NoError(t, err)

Expand Down
4 changes: 3 additions & 1 deletion proxy/serverudp_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ func TestUdpProxy(t *testing.T) {
dnsProxy := mustStartDefaultProxy(t)

// Create a DNS-over-UDP client connection
addr := dnsProxy.Addr(ProtoUDP)
addr, err := dnsProxy.Addr(ProtoUDP)
require.NoError(t, err)

conn, err := dns.Dial("udp", addr.String())
require.NoError(t, err)

Expand Down