From 884b69ba88c06cb2d1feb65f411c3235dc250482 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 20:50:58 +0000 Subject: [PATCH] Fix derived zone apex SOA responses --- serve.go | 9 +++++---- service_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/serve.go b/serve.go index 820e19c..d46cb61 100644 --- a/serve.go +++ b/serve.go @@ -184,10 +184,7 @@ func (handler *dnsRequestHandler) ServeDNS(responseWriter dnsprotocol.ResponseWr }) } case dnsprotocol.TypeSOA: - if !found { - goto noRecord - } - if normalizeName(name) == handler.service.ZoneApex() { + if normalizeName(name) == handler.service.ZoneApex() && handler.service.ZoneApex() != "" { reply.Answer = append(reply.Answer, &dnsprotocol.SOA{ Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypeSOA, Class: dnsprotocol.ClassINET, Ttl: dnsTTL}, Ns: normalizeName("ns."+name) + ".", @@ -198,6 +195,10 @@ func (handler *dnsRequestHandler) ServeDNS(responseWriter dnsprotocol.ResponseWr Expire: 3600, Minttl: 300, }) + break + } + if !found { + goto noRecord } default: reply.SetRcode(request, dnsprotocol.RcodeNotImplemented) diff --git a/service_test.go b/service_test.go index 83a7f19..0ad844b 100644 --- a/service_test.go +++ b/service_test.go @@ -1000,6 +1000,39 @@ func TestServiceServeAnswersSOAOnlyForZoneApex(t *testing.T) { } } +func TestServiceServeAnswersSOAForDerivedZoneApexWithoutExactRecord(t *testing.T) { + service := NewService(ServiceOptions{ + Records: map[string]NameRecords{ + "gateway.charon.lthn": { + A: []string{"10.10.10.10"}, + }, + "node.charon.lthn": { + A: []string{"10.10.10.11"}, + }, + }, + }) + + srv, err := service.Serve("127.0.0.1", 0) + if err != nil { + t.Fatalf("expected server to start: %v", err) + } + defer func() { _ = srv.Close() }() + + client := dnsprotocol.Client{} + request := new(dnsprotocol.Msg) + request.SetQuestion("charon.lthn.", dnsprotocol.TypeSOA) + response := exchangeWithRetry(t, client, request, srv.Address()) + if response.Rcode != dnsprotocol.RcodeSuccess { + t.Fatalf("expected SOA query for derived apex to succeed, got %d", response.Rcode) + } + if len(response.Answer) != 1 { + t.Fatalf("expected one SOA answer for derived apex, got %d", len(response.Answer)) + } + if _, ok := response.Answer[0].(*dnsprotocol.SOA); !ok { + t.Fatalf("expected SOA answer for derived apex, got %#v", response.Answer[0]) + } +} + func TestServiceServeReturnsNXDOMAINWhenMissing(t *testing.T) { service := NewService(ServiceOptions{}) -- 2.45.3