This commit is contained in:
Saleh 2026-07-04 13:29:45 +00:00 committed by GitHub
commit 783f2c7411
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 2 deletions

View file

@ -44,6 +44,7 @@ keys remain all-access.
- Expiring or deleting a non-existent pre-auth key now returns an error instead of silently succeeding [#3324](https://github.com/juanfont/headscale/pull/3324)
- Improve systemd service file hardening [#3341](https://github.com/juanfont/headscale/pull/3341)
- Lowercase DNS extra record names so mixed-case records resolve [#2782](https://github.com/juanfont/headscale/issues/2782)
## 0.29.2 (2026-07-01)

View file

@ -993,7 +993,7 @@ func dnsToTailcfgDNS(dns DNSConfig) *tailcfg.DNSConfig {
cfg.Proxied = dns.MagicDNS
cfg.ExtraRecords = dns.ExtraRecords
cfg.ExtraRecords = lowercaseRecordNames(dns.ExtraRecords)
if dns.OverrideLocalDNS {
cfg.Resolvers = dns.globalResolvers()
} else {
@ -1475,6 +1475,22 @@ func (c *Config) SetExtraRecords(records []tailcfg.DNSRecord) {
defer tailcfgDNSMu.Unlock()
if c.TailcfgDNSConfig != nil {
c.TailcfgDNSConfig.ExtraRecords = records
c.TailcfgDNSConfig.ExtraRecords = lowercaseRecordNames(records)
}
}
// lowercaseRecordNames normalizes DNS record names to lowercase, as DNS names
// are case-insensitive and clients match extra records by exact name.
func lowercaseRecordNames(records []tailcfg.DNSRecord) []tailcfg.DNSRecord {
if len(records) == 0 {
return records
}
normalized := make([]tailcfg.DNSRecord, len(records))
for i, record := range records {
record.Name = strings.ToLower(record.Name)
normalized[i] = record
}
return normalized
}

View file

@ -741,3 +741,33 @@ func TestTrustedProxies(t *testing.T) {
})
}
}
// DNS names are case-insensitive, but MagicDNS resolution in clients matches
// extra records by exact name, so mixed-case record names never resolve.
// See https://github.com/juanfont/headscale/issues/2782.
func TestExtraRecordsAreLowercased(t *testing.T) {
mixed := []tailcfg.DNSRecord{
{Name: "Printer.fritz.box", Type: "A", Value: "192.168.1.2"},
{Name: "NAS.FRITZ.BOX", Type: "A", Value: "192.168.1.3"},
}
want := []tailcfg.DNSRecord{
{Name: "printer.fritz.box", Type: "A", Value: "192.168.1.2"},
{Name: "nas.fritz.box", Type: "A", Value: "192.168.1.3"},
}
tcfg := dnsToTailcfgDNS(DNSConfig{
MagicDNS: true,
BaseDomain: "example.com",
ExtraRecords: mixed,
})
if diff := cmp.Diff(want, tcfg.ExtraRecords); diff != "" {
t.Errorf("dnsToTailcfgDNS extra records mismatch (-want +got):\n%s", diff)
}
cfg := &Config{TailcfgDNSConfig: &tailcfg.DNSConfig{}}
cfg.SetExtraRecords(mixed)
if diff := cmp.Diff(want, cfg.TailcfgDNSConfig.ExtraRecords); diff != "" {
t.Errorf("SetExtraRecords mismatch (-want +got):\n%s", diff)
}
}