From d2f7d59fce9125d6f32f2173f7ef8bb2c6a6ec27 Mon Sep 17 00:00:00 2001 From: Mechiel Lukkien <mechiel@ueber.net> Date: Mon, 12 Jun 2023 14:45:29 +0200 Subject: [PATCH] for dns resolve errors likely due to a missing name server in /etc/resolv.conf, point user to man page of systemd-resolved, the likely cause it seems linux machines with systemd-resolved don't always set up /etc/resolv.conf correctly. there may be no "nameserver" entry, causing Go's net resolver to fallback to 127.0.0.1 and ::1. Systemd-resolved is listening on 127.0.0.53, so users will likely get a "connection refused". So point users to the systemd-resolved manual page. for issue #38 by ArnoSen --- dns/resolver.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/dns/resolver.go b/dns/resolver.go index ac04341..0a61311 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -3,8 +3,10 @@ package dns import ( "context" "errors" + "fmt" "net" "os" + "runtime" "strings" "time" @@ -104,12 +106,29 @@ func (r StrictResolver) resolver() Resolver { return r.Resolver } +func resolveErrorHint(err *error) { + e := *err + if e == nil { + return + } + dnserr, ok := e.(*net.DNSError) + if !ok { + return + } + // If the dns server is not running, and it is one of the default/fallback IPs, + // hint at where to look. + if dnserr.IsTemporary && runtime.GOOS == "linux" && (dnserr.Server == "127.0.0.1:53" || dnserr.Server == "[::1]:53") && strings.HasSuffix(dnserr.Err, "connection refused") { + *err = fmt.Errorf("%w (hint: does /etc/resolv.conf point to a running nameserver? in case of systemd-resolved, see systemd-resolved.service(8))", *err) + } +} + func (r StrictResolver) LookupAddr(ctx context.Context, addr string) (resp []string, err error) { start := time.Now() defer func() { metricLookupObserve(r.Pkg, "addr", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "addr"), mlog.Field("addr", addr), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) resp, err = r.resolver().LookupAddr(ctx, addr) return @@ -123,6 +142,7 @@ func (r StrictResolver) LookupCNAME(ctx context.Context, host string) (resp stri metricLookupObserve(r.Pkg, "cname", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "cname"), mlog.Field("host", host), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(host, ".") { return "", ErrRelativeDNSName @@ -144,6 +164,7 @@ func (r StrictResolver) LookupHost(ctx context.Context, host string) (resp []str metricLookupObserve(r.Pkg, "host", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "host"), mlog.Field("host", host), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(host, ".") { return nil, ErrRelativeDNSName @@ -158,6 +179,7 @@ func (r StrictResolver) LookupIP(ctx context.Context, network, host string) (res metricLookupObserve(r.Pkg, "ip", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "ip"), mlog.Field("network", network), mlog.Field("host", host), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(host, ".") { return nil, ErrRelativeDNSName @@ -172,6 +194,7 @@ func (r StrictResolver) LookupIPAddr(ctx context.Context, host string) (resp []n metricLookupObserve(r.Pkg, "ipaddr", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "ipaddr"), mlog.Field("host", host), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(host, ".") { return nil, ErrRelativeDNSName @@ -186,6 +209,7 @@ func (r StrictResolver) LookupMX(ctx context.Context, name string) (resp []*net. metricLookupObserve(r.Pkg, "mx", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "mx"), mlog.Field("name", name), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(name, ".") { return nil, ErrRelativeDNSName @@ -200,6 +224,7 @@ func (r StrictResolver) LookupNS(ctx context.Context, name string) (resp []*net. metricLookupObserve(r.Pkg, "ns", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "ns"), mlog.Field("name", name), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(name, ".") { return nil, ErrRelativeDNSName @@ -214,6 +239,7 @@ func (r StrictResolver) LookupPort(ctx context.Context, network, service string) metricLookupObserve(r.Pkg, "port", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "port"), mlog.Field("network", network), mlog.Field("service", service), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) resp, err = r.resolver().LookupPort(ctx, network, service) return @@ -225,6 +251,7 @@ func (r StrictResolver) LookupSRV(ctx context.Context, service, proto, name stri metricLookupObserve(r.Pkg, "srv", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "srv"), mlog.Field("service", service), mlog.Field("proto", proto), mlog.Field("name", name), mlog.Field("resp0", resp0), mlog.Field("resp1", resp1), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(name, ".") { return "", nil, ErrRelativeDNSName @@ -239,6 +266,7 @@ func (r StrictResolver) LookupTXT(ctx context.Context, name string) (resp []stri metricLookupObserve(r.Pkg, "txt", err, start) xlog.WithContext(ctx).Debugx("dns lookup result", err, mlog.Field("pkg", r.Pkg), mlog.Field("type", "txt"), mlog.Field("name", name), mlog.Field("resp", resp), mlog.Field("duration", time.Since(start))) }() + defer resolveErrorHint(&err) if !strings.HasSuffix(name, ".") { return nil, ErrRelativeDNSName