From f27ec3438add75ab9071b4d8261b4d62b6e2a4e8 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 23:03:17 +0000 Subject: [PATCH] feat(service): include wildcard suffixes when computing zone apex Co-Authored-By: Virgil --- service.go | 5 +++ service_test.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/service.go b/service.go index a293731..11160b4 100644 --- a/service.go +++ b/service.go @@ -1045,6 +1045,11 @@ func computeZoneApex(records map[string]NameRecords) string { names := make([]string, 0, len(records)) for name := range records { if strings.HasPrefix(name, "*.") { + suffix := strings.TrimPrefix(name, "*.") + if suffix == "" { + continue + } + names = append(names, suffix) continue } names = append(names, name) diff --git a/service_test.go b/service_test.go index f31fe6e..07ebe73 100644 --- a/service_test.go +++ b/service_test.go @@ -1848,6 +1848,38 @@ func TestServiceServeAnswersSOAForDerivedZoneApexWithoutExactRecord(t *testing.T } } +func TestServiceServeAnswersSOAForWildcardOnlyDerivedZoneApex(t *testing.T) { + service := NewService(ServiceOptions{ + Records: map[string]NameRecords{ + "*.charon.lthn": { + A: []string{"10.0.0.1"}, + }, + }, + }) + + 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 wildcard-derived apex to succeed, got %d", response.Rcode) + } + if len(response.Answer) != 1 { + t.Fatalf("expected one SOA answer for wildcard-derived apex, got %d", len(response.Answer)) + } + if _, ok := response.Answer[0].(*dnsprotocol.SOA); !ok { + t.Fatalf("expected SOA answer for wildcard-derived apex, got %#v", response.Answer[0]) + } +} + func TestServiceServeAnswersNSForDerivedZoneApexWithoutExactRecord(t *testing.T) { service := NewService(ServiceOptions{ Records: map[string]NameRecords{ @@ -1885,6 +1917,42 @@ func TestServiceServeAnswersNSForDerivedZoneApexWithoutExactRecord(t *testing.T) } } +func TestServiceServeAnswersNSForWildcardOnlyDerivedZoneApex(t *testing.T) { + service := NewService(ServiceOptions{ + Records: map[string]NameRecords{ + "*.gateway.charon.lthn": { + A: []string{"10.0.0.1"}, + }, + }, + }) + + 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("gateway.charon.lthn.", dnsprotocol.TypeNS) + response := exchangeWithRetry(t, client, request, srv.Address()) + if response.Rcode != dnsprotocol.RcodeSuccess { + t.Fatalf("expected NS query for wildcard-derived apex to succeed, got %d", response.Rcode) + } + if len(response.Answer) != 1 { + t.Fatalf("expected one NS answer for wildcard-derived apex, got %d", len(response.Answer)) + } + ns, ok := response.Answer[0].(*dnsprotocol.NS) + if !ok { + t.Fatalf("expected NS answer for wildcard-derived apex, got %#v", response.Answer[0]) + } + if ns.Ns != "ns.gateway.charon.lthn." { + t.Fatalf("expected synthesized wildcard-derived apex NS, got %q", ns.Ns) + } +} + func TestServiceResolveAllSynthesizesNSForDerivedZoneApex(t *testing.T) { service := NewService(ServiceOptions{ Records: map[string]NameRecords{ @@ -1906,6 +1974,27 @@ func TestServiceResolveAllSynthesizesNSForDerivedZoneApex(t *testing.T) { } } +func TestServiceResolveAllSynthesizesNSForWildcardOnlyDerivedZoneApex(t *testing.T) { + service := NewService(ServiceOptions{ + Records: map[string]NameRecords{ + "*.charon.lthn": { + A: []string{"10.0.0.1"}, + }, + }, + }) + + result, ok := service.ResolveAll("charon.lthn") + if !ok { + t.Fatal("expected wildcard-derived zone apex to resolve") + } + if len(result.A) != 0 || len(result.AAAA) != 0 || len(result.TXT) != 0 { + t.Fatalf("expected no A/AAAA/TXT values for derived wildcard apex, got %#v", result) + } + if len(result.NS) != 1 || result.NS[0] != "ns.charon.lthn" { + t.Fatalf("expected synthesized NS from wildcard-derived apex, got %#v", result.NS) + } +} + func TestServiceResolveAllReturnsStableShapeForDerivedZoneApex(t *testing.T) { service := NewService(ServiceOptions{ Records: map[string]NameRecords{