feat(health/dns): try another DNS server if one fails

This commit is contained in:
Quentin McGaw
2025-11-04 15:51:04 +00:00
parent 1047508bd7
commit 2bd19640d9

View File

@@ -5,33 +5,60 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/netip"
"github.com/qdm12/dns/v2/pkg/provider"
) )
// Client is a simple plaintext UDP DNS client, to be used for healthchecks. // Client is a simple plaintext UDP DNS client, to be used for healthchecks.
// Note the client connects to a DNS server only over UDP on port 53, // Note the client connects to a DNS server only over UDP on port 53,
// because we don't want to use DoT or DoH and impact the TCP connections // because we don't want to use DoT or DoH and impact the TCP connections
// when running a healthcheck. // when running a healthcheck.
type Client struct{} type Client struct {
serverAddrs []netip.AddrPort
dnsIPIndex int
}
func New() *Client { func New() *Client {
return &Client{} return &Client{
serverAddrs: concatAddrPorts([][]netip.AddrPort{
provider.Cloudflare().Plain.IPv4,
provider.Google().Plain.IPv4,
provider.Quad9().Plain.IPv4,
provider.OpenDNS().Plain.IPv4,
provider.LibreDNS().Plain.IPv4,
provider.Quadrant().Plain.IPv4,
provider.CiraProtected().Plain.IPv4,
}),
}
}
func concatAddrPorts(addrs [][]netip.AddrPort) []netip.AddrPort {
var result []netip.AddrPort
for _, addrList := range addrs {
result = append(result, addrList...)
}
return result
} }
var ErrLookupNoIPs = errors.New("no IPs found from DNS lookup") var ErrLookupNoIPs = errors.New("no IPs found from DNS lookup")
func (c *Client) Check(ctx context.Context) error { func (c *Client) Check(ctx context.Context) error {
dnsAddr := c.serverAddrs[c.dnsIPIndex].Addr()
resolver := &net.Resolver{ resolver := &net.Resolver{
PreferGo: true, PreferGo: true,
Dial: func(ctx context.Context, _, _ string) (net.Conn, error) { Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
dialer := net.Dialer{} dialer := net.Dialer{}
return dialer.DialContext(ctx, "udp", "1.1.1.1:53") return dialer.DialContext(ctx, "udp", dnsAddr.String())
}, },
} }
ips, err := resolver.LookupIP(ctx, "ip", "github.com") ips, err := resolver.LookupIP(ctx, "ip", "github.com")
switch { switch {
case err != nil: case err != nil:
c.dnsIPIndex = (c.dnsIPIndex + 1) % len(c.serverAddrs)
return err return err
case len(ips) == 0: case len(ips) == 0:
c.dnsIPIndex = (c.dnsIPIndex + 1) % len(c.serverAddrs)
return fmt.Errorf("%w", ErrLookupNoIPs) return fmt.Errorf("%w", ErrLookupNoIPs)
default: default:
return nil return nil