fix(zonefinder): handle underscores in dns records

Signed-off-by: Arthur Le Roux <arthurleroux@protonmail.com>
This commit is contained in:
Arthur Le Roux 2025-04-13 10:32:22 +02:00 committed by Arthur Le Roux
parent 2de3b50b14
commit 64f7989628
2 changed files with 32 additions and 6 deletions

View File

@ -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) {

View File

@ -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\"")
}