mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 16:29:56 +00:00
TUN-9473: Add --dns-resolver-addrs flag
To help support users with environments that don't work well with the DNS local resolver's automatic resolution process for local resolver addresses, we introduce a flag to provide them statically to the runtime. When providing the resolver addresses, cloudflared will no longer lookup the DNS resolver addresses and use the user input directly. When provided with a list of DNS resolvers larger than one, the resolver service will randomly select one at random for each incoming request. Closes TUN-9473
This commit is contained in:
@@ -5,7 +5,9 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
@@ -17,9 +19,18 @@ func TestDNSResolver_DefaultResolver(t *testing.T) {
|
||||
address: "127.0.0.2:53",
|
||||
}
|
||||
service.resolver = mockResolver
|
||||
if service.address != defaultResolverAddr {
|
||||
t.Errorf("resolver address should be the default: %s, was: %s", defaultResolverAddr, service.address)
|
||||
validateAddrs(t, []netip.AddrPort{defaultResolverAddr}, service.addresses)
|
||||
}
|
||||
|
||||
func TestStaticDNSResolver_DefaultResolver(t *testing.T) {
|
||||
log := zerolog.Nop()
|
||||
addresses := []netip.AddrPort{netip.MustParseAddrPort("1.1.1.1:53"), netip.MustParseAddrPort("1.0.0.1:53")}
|
||||
service := NewStaticDNSResolverService(addresses, NewDNSDialer(), &log)
|
||||
mockResolver := &mockPeekResolver{
|
||||
address: "127.0.0.2:53",
|
||||
}
|
||||
service.resolver = mockResolver
|
||||
validateAddrs(t, addresses, service.addresses)
|
||||
}
|
||||
|
||||
func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
|
||||
@@ -29,26 +40,49 @@ func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
|
||||
mockResolver := &mockPeekResolver{}
|
||||
service.resolver = mockResolver
|
||||
|
||||
expectedAddr := netip.MustParseAddrPort("127.0.0.2:53")
|
||||
addresses := []string{
|
||||
"127.0.0.2:53",
|
||||
"127.0.0.2", // missing port should be added (even though this is unlikely to happen)
|
||||
tests := []struct {
|
||||
addr string
|
||||
expected netip.AddrPort
|
||||
}{
|
||||
{"127.0.0.2:53", netip.MustParseAddrPort("127.0.0.2:53")},
|
||||
// missing port should be added (even though this is unlikely to happen)
|
||||
{"127.0.0.3", netip.MustParseAddrPort("127.0.0.3:53")},
|
||||
}
|
||||
|
||||
for _, addr := range addresses {
|
||||
mockResolver.address = addr
|
||||
for _, test := range tests {
|
||||
mockResolver.address = test.addr
|
||||
// Update the resolver address
|
||||
err := service.update(t.Context())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
// Validate expected
|
||||
if service.address != expectedAddr {
|
||||
t.Errorf("resolver address should be: %s, was: %s", expectedAddr, service.address)
|
||||
}
|
||||
validateAddrs(t, []netip.AddrPort{test.expected}, service.addresses)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStaticDNSResolver_RefreshLoopExits(t *testing.T) {
|
||||
log := zerolog.Nop()
|
||||
addresses := []netip.AddrPort{netip.MustParseAddrPort("1.1.1.1:53"), netip.MustParseAddrPort("1.0.0.1:53")}
|
||||
service := NewStaticDNSResolverService(addresses, NewDNSDialer(), &log)
|
||||
|
||||
mockResolver := &mockPeekResolver{
|
||||
address: "127.0.0.2:53",
|
||||
}
|
||||
service.resolver = mockResolver
|
||||
|
||||
ctx, cancel := context.WithCancel(t.Context())
|
||||
defer cancel()
|
||||
|
||||
go service.StartRefreshLoop(ctx)
|
||||
|
||||
// Wait for the refresh loop to end _and_ not update the addresses
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Validate expected
|
||||
validateAddrs(t, addresses, service.addresses)
|
||||
}
|
||||
|
||||
func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
|
||||
log := zerolog.Nop()
|
||||
service := NewDNSResolverService(NewDNSDialer(), &log)
|
||||
@@ -69,9 +103,7 @@ func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
|
||||
t.Error("service update should throw an error")
|
||||
}
|
||||
// Validate expected
|
||||
if service.address != defaultResolverAddr {
|
||||
t.Errorf("resolver address should not be updated from default: %s, was: %s", defaultResolverAddr, service.address)
|
||||
}
|
||||
validateAddrs(t, []netip.AddrPort{defaultResolverAddr}, service.addresses)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +120,7 @@ func TestDNSResolver_UpdateResolverErrorIgnored(t *testing.T) {
|
||||
t.Error("service update should throw an error")
|
||||
}
|
||||
// Validate expected
|
||||
if service.address != defaultResolverAddr {
|
||||
t.Errorf("resolver address should not be updated from default: %s, was: %s", defaultResolverAddr, service.address)
|
||||
}
|
||||
validateAddrs(t, []netip.AddrPort{defaultResolverAddr}, service.addresses)
|
||||
}
|
||||
|
||||
func TestDNSResolver_DialUDPUsesResolvedAddress(t *testing.T) {
|
||||
@@ -152,3 +182,14 @@ func (d *mockDialer) DialUDP(addr netip.AddrPort) (net.Conn, error) {
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func validateAddrs(t *testing.T, expected []netip.AddrPort, actual []netip.AddrPort) {
|
||||
if len(actual) != len(expected) {
|
||||
t.Errorf("addresses should only contain one element: %s", actual)
|
||||
}
|
||||
for _, e := range expected {
|
||||
if !slices.Contains(actual, e) {
|
||||
t.Errorf("missing address: %s in %s", e, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user