diff --git a/provider/zonefinder.go b/provider/zonefinder.go index 6a07646c1..a81f997b3 100644 --- a/provider/zonefinder.go +++ b/provider/zonefinder.go @@ -29,12 +29,34 @@ func (z ZoneIDName) Add(zoneID, zoneName string) { z[zoneID] = zoneName } +// FindZone identifies the most suitable DNS zone for a given hostname. +// It returns the zone ID and name that best match the hostname. +// +// The function processes the hostname by splitting it into labels and +// converting each label to its Unicode form using IDNA (Internationalized +// Domain Names for Applications) standards. +// +// Labels containing underscores ('_') are skipped during Unicode conversion. +// This is because underscores are often used in special DNS records (e.g., +// SRV records as per RFC 2782, or TXT record for services) that are not +// IDNA-aware and cannot represent non-ASCII labels. Skipping these labels +// ensures compatibility with such use cases. func (z ZoneIDName) FindZone(hostname string) (suitableZoneID, suitableZoneName string) { - name, err := idna.Lookup.ToUnicode(hostname) - if err != nil { - log.Warnf("Failed to convert hostname '%s' to its Unicode form: %v", hostname, err) - name = hostname + var name string + domain_labels := strings.Split(hostname, ".") + for i, label := range domain_labels { + if strings.Contains(label, "_") { + continue + } + convertedLabel, err := idna.Lookup.ToUnicode(label) + if err != nil { + log.Warnf("Failed to convert label '%s' of hostname '%s' to its Unicode form: %v", label, hostname, err) + convertedLabel = label + } + domain_labels[i] = convertedLabel } + name = strings.Join(domain_labels, ".") + for zoneID, zoneName := range z { if name == zoneName || strings.HasSuffix(name, "."+zoneName) { if suitableZoneName == "" || len(zoneName) > len(suitableZoneName) { diff --git a/provider/zonefinder_test.go b/provider/zonefinder_test.go index 0037edadd..8b33f566f 100644 --- a/provider/zonefinder_test.go +++ b/provider/zonefinder_test.go @@ -30,11 +30,15 @@ func TestZoneIDName(t *testing.T) { z.Add("123456", "qux.baz") z.Add("654321", "foo.qux.baz") z.Add("987654", "エイミー.みんな") + z.Add("123123", "_metadata.example.com") + z.Add("456456", "_metadata.エイミー.みんな") assert.Equal(t, ZoneIDName{ "123456": "qux.baz", "654321": "foo.qux.baz", "987654": "エイミー.みんな", + "123123": "_metadata.example.com", + "456456": "_metadata.エイミー.みんな", }, z) // simple entry in a domain @@ -73,6 +77,6 @@ func TestZoneIDName(t *testing.T) { assert.Equal(t, "987654", zoneID) b := testutils.LogsToBuffer(log.WarnLevel, t) - zoneID, zoneName = z.FindZone("???") - assert.Contains(t, b.String(), "level=warning msg=\"Failed to convert hostname '???' to its Unicode form: idna: disallowed rune U+003F\"") + _, _ = z.FindZone("???") + assert.Contains(t, b.String(), "level=warning msg=\"Failed to convert label '???' of hostname '???' to its Unicode form: idna: disallowed rune U+003F\"") }