checker: add dname_coexistence rule and refactor sibling probing
Extract querySiblings from observeCoexistence so both CNAME and DNAME coexistence checks share the same parallel RRset scan. Add observeDNAMECoexistence (called from Collect) that populates AliasData.DNAMECoexistence for each DNAME node in DNAMESubstitutions. Add the dname_coexistence rule (RFC 6672 §2.3) that flags any sibling RRsets at a DNAME owner as CRIT, with matching tests.
This commit is contained in:
parent
1493ef4d3f
commit
c5c13960d5
5 changed files with 112 additions and 12 deletions
|
|
@ -49,6 +49,7 @@ func (p *aliasProvider) Collect(ctx context.Context, opts sdk.CheckerOptions) (a
|
|||
}
|
||||
|
||||
observeCoexistence(ctx, data, servers, owner)
|
||||
observeDNAMECoexistence(ctx, data, servers)
|
||||
observeDNSSEC(ctx, data, servers, apex, owner)
|
||||
|
||||
return data, nil
|
||||
|
|
@ -403,20 +404,18 @@ func observeApex(ctx context.Context, data *AliasData, servers []string, apex st
|
|||
}
|
||||
}
|
||||
|
||||
func observeCoexistence(ctx context.Context, data *AliasData, servers []string, owner string) {
|
||||
if !data.OwnerHasCNAME {
|
||||
return
|
||||
}
|
||||
|
||||
siblings := []uint16{
|
||||
// querySiblings returns RRsets of common types that sit alongside a CNAME or DNAME at owner.
|
||||
// Filter on owner+type: a DNAME-synthesized CNAME would otherwise count as a sibling.
|
||||
func querySiblings(ctx context.Context, servers []string, owner string) []CoexistingRRset {
|
||||
candidates := []uint16{
|
||||
dns.TypeA, dns.TypeAAAA, dns.TypeMX, dns.TypeTXT,
|
||||
dns.TypeNS, dns.TypeSRV, dns.TypeCAA,
|
||||
}
|
||||
seen := map[string]uint32{}
|
||||
var mu sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(siblings))
|
||||
for _, qt := range siblings {
|
||||
wg.Add(len(candidates))
|
||||
for _, qt := range candidates {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
q := dns.Question{Name: owner, Qtype: qt, Qclass: dns.ClassINET}
|
||||
|
|
@ -424,8 +423,6 @@ func observeCoexistence(ctx context.Context, data *AliasData, servers []string,
|
|||
if err != nil || r == nil {
|
||||
return
|
||||
}
|
||||
// Filter on owner+type because a DNAME-synthesized CNAME would
|
||||
// otherwise count as a sibling of every queried type.
|
||||
for _, rr := range r.Answer {
|
||||
if rr.Header().Rrtype != qt {
|
||||
continue
|
||||
|
|
@ -441,9 +438,42 @@ func observeCoexistence(ctx context.Context, data *AliasData, servers []string,
|
|||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
var out []CoexistingRRset
|
||||
for t, ttl := range seen {
|
||||
data.Coexisting = append(data.Coexisting, CoexistingRRset{Type: t, TTL: ttl})
|
||||
out = append(out, CoexistingRRset{Type: t, TTL: ttl})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func observeCoexistence(ctx context.Context, data *AliasData, servers []string, owner string) {
|
||||
if !data.OwnerHasCNAME {
|
||||
return
|
||||
}
|
||||
data.Coexisting = querySiblings(ctx, servers, owner)
|
||||
}
|
||||
|
||||
func observeDNAMECoexistence(ctx context.Context, data *AliasData, servers []string) {
|
||||
if len(data.DNAMESubstitutions) == 0 {
|
||||
return
|
||||
}
|
||||
results := make(map[string][]CoexistingRRset, len(data.DNAMESubstitutions))
|
||||
var mu sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(data.DNAMESubstitutions))
|
||||
for _, hop := range data.DNAMESubstitutions {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
siblings := querySiblings(ctx, servers, hop.Owner)
|
||||
if len(siblings) > 0 {
|
||||
mu.Lock()
|
||||
results[hop.Owner] = siblings
|
||||
mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
if len(results) > 0 {
|
||||
data.DNAMECoexistence = results
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue