From 59d33eb06a48560384b0d271ce923029e058d25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20J=C3=A4ckel?= Date: Tue, 4 Feb 2025 19:57:54 +0100 Subject: [PATCH] Replace hardcoded 1.1.1.1 dns server with resolve.conf parsing --- dns.go | 31 ++++++++++++++++++++++++++----- experiments/dns/dnsproxy.go | 32 ++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/dns.go b/dns.go index e081efd..5c15964 100644 --- a/dns.go +++ b/dns.go @@ -2,9 +2,11 @@ package main import ( "context" + "errors" "fmt" "io" "net" + "strings" "github.com/miekg/dns" ) @@ -236,8 +238,6 @@ func dnsTypeCode(t uint16) string { // handleDNSQuery resolves IPv4 hostnames according to net.DefaultResolver func handleDNSQuery(ctx context.Context, req *dns.Msg) ([]dns.RR, error) { - const upstreamDNS = "1.1.1.1:53" // TODO: get from resolv.conf and nsswitch.conf - if len(req.Question) == 0 { return nil, nil // this means no answer, no error, which is fine } @@ -285,6 +285,11 @@ func handleDNSQuery(ctx context.Context, req *dns.Msg) ([]dns.RR, error) { verbose("proxying non-A request to upstream DNS server...") + dnsClientConfig, err := dns.ClientConfigFromFile("/etc/resolv.conf") + if err != nil { + return nil, fmt.Errorf("could not parse /etc/resolv.conf: %w", err) + } + // proxy the request to another server request := new(dns.Msg) req.CopyTo(request) @@ -292,9 +297,25 @@ func handleDNSQuery(ctx context.Context, req *dns.Msg) ([]dns.RR, error) { dnsClient := new(dns.Client) dnsClient.Net = "udp" - response, _, err := dnsClient.Exchange(request, upstreamDNS) - if err != nil { - return nil, err + var ( + response *dns.Msg + errs []error + ) + for _, dnsServer := range dnsClientConfig.Servers { + response, _, err = dnsClient.Exchange(request, dnsServer) + if err != nil { + errs = append(errs, err) + continue + } + break + } + + if len(errs) > 0 { + var errStr []string + for _, err := range errs { + errStr = append(errStr, err.Error()) + } + return nil, errors.New(strings.Join(errStr, ", ")) } verbosef("got answer from upstream dns server with %d answers", len(response.Answer)) diff --git a/experiments/dns/dnsproxy.go b/experiments/dns/dnsproxy.go index 3f4c434..97ed232 100644 --- a/experiments/dns/dnsproxy.go +++ b/experiments/dns/dnsproxy.go @@ -2,19 +2,18 @@ package main import ( "context" + "errors" "fmt" "log" "net" "os" + "strings" "github.com/alexflint/go-arg" "github.com/miekg/dns" ) -const upstreamDNS = "1.1.1.1:53" // TODO: get from resolv.conf and nsswitch.conf - // handle resolves IPv4 hosts according to net.DefaultResolver - func handle(requestMsg *dns.Msg) ([]dns.RR, error) { if len(requestMsg.Question) == 0 { return nil, nil // this means no answer, no error, which is fine @@ -47,6 +46,11 @@ func handle(requestMsg *dns.Msg) ([]dns.RR, error) { log.Println("proxying the request...") + dnsClientConfig, err := dns.ClientConfigFromFile("/etc/resolv.conf") + if err != nil { + return nil, fmt.Errorf("could not parse /etc/resolv.conf: %w", err) + } + // proxy the request to another server queryMsg := new(dns.Msg) requestMsg.CopyTo(queryMsg) @@ -54,9 +58,25 @@ func handle(requestMsg *dns.Msg) ([]dns.RR, error) { dnsClient := new(dns.Client) dnsClient.Net = "udp" - response, _, err := dnsClient.Exchange(queryMsg, upstreamDNS) - if err != nil { - return nil, err + var ( + response *dns.Msg + errs []error + ) + for _, dnsServer := range dnsClientConfig.Servers { + response, _, err = dnsClient.Exchange(queryMsg, dnsServer) + if err != nil { + errs = append(errs, err) + continue + } + break + } + + if len(errs) > 0 { + var errStr []string + for _, err := range errs { + errStr = append(errStr, err.Error()) + } + return nil, errors.New(strings.Join(errStr, ", ")) } log.Printf("got answer from upstream dns server with %d answers", len(response.Answer))