From 474f012b4dc15e836c82e2e9ff1371a43ee4f3eb Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Tue, 16 Jun 2020 01:07:17 +0200 Subject: [PATCH] Add support for IDNA Signed-off-by: Julien Pivotto --- prober/dns.go | 9 +++++++-- prober/utils.go | 18 ++++++++++++++++++ prober/utils_test.go | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/prober/dns.go b/prober/dns.go index edb5b2820..cf6a36d84 100644 --- a/prober/dns.go +++ b/prober/dns.go @@ -209,12 +209,17 @@ func ProbeDNS(ctx context.Context, target string, module config.Module, registry } } + idnTarget, err := internationalizeDNSTarget(logger, module.DNS.QueryName) + if err != nil { + level.Error(logger).Log("msg", "IDN conversion failed", "err", err) + return false + } + msg := new(dns.Msg) msg.Id = dns.Id() msg.RecursionDesired = true msg.Question = make([]dns.Question, 1) - msg.Question[0] = dns.Question{dns.Fqdn(module.DNS.QueryName), qt, qc} - + msg.Question[0] = dns.Question{dns.Fqdn(idnTarget), qt, qc} level.Info(logger).Log("msg", "Making DNS query", "target", target, "dial_protocol", dialProtocol, "query", module.DNS.QueryName, "type", qt, "class", qc) timeoutDeadline, _ := ctx.Deadline() client.Timeout = time.Until(timeoutDeadline) diff --git a/prober/utils.go b/prober/utils.go index 98c9152ea..76b62e60d 100644 --- a/prober/utils.go +++ b/prober/utils.go @@ -22,6 +22,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" + "golang.org/x/net/idna" "github.com/prometheus/client_golang/prometheus" ) @@ -55,6 +56,12 @@ func chooseProtocol(ctx context.Context, IPProtocol string, fallbackIPProtocol b fallbackProtocol = "ip6" } + target, err = internationalizeDNSTarget(logger, target) + if err != nil { + level.Error(logger).Log("msg", "IDN conversion failed", "err", err) + return nil, 0.0, err + } + level.Info(logger).Log("msg", "Resolving target address", "ip_protocol", IPProtocol) resolveStart := time.Now() @@ -119,3 +126,14 @@ func ipHash(ip net.IP) float64 { h.Write(ip) return float64(h.Sum32()) } + +func internationalizeDNSTarget(logger log.Logger, target string) (string, error) { + idnaTarget, err := idna.ToASCII(target) + if err != nil { + return target, fmt.Errorf("error while internationalizing target: %w", err) + } + if idnaTarget != target { + level.Info(logger).Log("msg", "Target address internationalized", "ascii", idnaTarget) + } + return idnaTarget, nil +} diff --git a/prober/utils_test.go b/prober/utils_test.go index 2ac38eebe..7cc3d734d 100644 --- a/prober/utils_test.go +++ b/prober/utils_test.go @@ -171,3 +171,23 @@ func TestChooseProtocol(t *testing.T) { t.Error("without fallback it should not answer") } } + +func TestChooseProtocolIDNA(t *testing.T) { + if testing.Short() { + t.Skip("skipping network dependent test") + } + var ( + ctx = context.Background() + registry = prometheus.NewPedanticRegistry() + w = log.NewSyncWriter(os.Stderr) + logger = log.NewLogfmtLogger(w) + ) + + ip, _, err := chooseProtocol(ctx, "ip4", true, "www.académie-française.fr", registry, logger) + if err != nil { + t.Error(err) + } + if ip == nil || ip.IP.To4() == nil { + t.Error("it should answer") + } +}