From 37db83e5b726e7248bd86e48783bb1fe6b4f5729 Mon Sep 17 00:00:00 2001 From: Ward Vandewege <cure@users.noreply.github.com> Date: Thu, 7 Feb 2019 02:16:33 -0500 Subject: [PATCH] Respond case insensitively to A and SOA requests (#152) * When appending the SOA for authoritative NXDOMAIN responses, it needs to go in the Authoritative section, not the Answer section. This fixes the acme-dns validation for the lego Let's Encrypt client. * Respond case-insensitively to A and SOA requests. Add corresponding tests. This fixes the autocert feature with Let's Encrypt, because Let's Encrypt does a lookup for the A record with a deliberately mangled case. --- dns.go | 6 +++--- dns_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/dns.go b/dns.go index 3ca0753..baf54a8 100644 --- a/dns.go +++ b/dns.go @@ -113,7 +113,7 @@ func (d *DNSServer) readQuery(m *dns.Msg) { func (d *DNSServer) getRecord(q dns.Question) ([]dns.RR, error) { var rr []dns.RR var cnames []dns.RR - domain, ok := d.Domains[q.Name] + domain, ok := d.Domains[strings.ToLower(q.Name)] if !ok { return rr, fmt.Errorf("No records for domain %s", q.Name) } @@ -133,7 +133,7 @@ func (d *DNSServer) getRecord(q dns.Question) ([]dns.RR, error) { // answeringForDomain checks if we have any records for a domain func (d *DNSServer) answeringForDomain(name string) bool { - _, ok := d.Domains[name] + _, ok := d.Domains[strings.ToLower(name)] return ok } @@ -141,7 +141,7 @@ func (d *DNSServer) isAuthoritative(q dns.Question) bool { if d.answeringForDomain(q.Name) { return true } - domainParts := strings.Split(q.Name, ".") + domainParts := strings.Split(strings.ToLower(q.Name), ".") for i := range domainParts { if d.answeringForDomain(strings.Join(domainParts[i:], ".")) { return true diff --git a/dns_test.go b/dns_test.go index 044e9a0..83723f8 100644 --- a/dns_test.go +++ b/dns_test.go @@ -218,3 +218,27 @@ func TestResolveTXT(t *testing.T) { } } } + +func TestCaseInsensitiveResolveA(t *testing.T) { + resolv := resolver{server: "127.0.0.1:15353"} + answer, err := resolv.lookup("aUtH.eXAmpLe.org", dns.TypeA) + if err != nil { + t.Errorf("%v", err) + } + + if len(answer.Answer) == 0 { + t.Error("No answer for DNS query") + } +} + +func TestCaseInsensitiveResolveSOA(t *testing.T) { + resolv := resolver{server: "127.0.0.1:15353"} + answer, _ := resolv.lookup("doesnotexist.aUtH.eXAmpLe.org", dns.TypeSOA) + if answer.Rcode != dns.RcodeNameError { + t.Errorf("Was expecing NXDOMAIN rcode, but got [%s] instead.", dns.RcodeToString[answer.Rcode]) + } + + if len(answer.Ns) == 0 { + t.Error("No SOA answer for DNS query") + } +} -- GitLab