This commit is contained in:
developer committed 2026-09-28 10:37:15 +00:00
1 parent d94e4cf6a8
commit b2cd7d4b91
13 files changed
+542 -26

No files matched your search

+58 -1
View File
@@ -2,7 +2,9 @@ package app
import (
"context"
"errors"
"fmt"
"net/netip"
"sort"
"strings"
"sync"
@@ -13,6 +15,7 @@ import (
"git.k8s-git-k6n.net/mats/fancy-dns/internal/api"
"git.k8s-git-k6n.net/mats/fancy-dns/internal/blocklist"
"git.k8s-git-k6n.net/mats/fancy-dns/internal/config"
"git.k8s-git-k6n.net/mats/fancy-dns/internal/engine"
"git.k8s-git-k6n.net/mats/fancy-dns/internal/metrics"
"git.k8s-git-k6n.net/mats/fancy-dns/internal/qlog"
"git.k8s-git-k6n.net/mats/fancy-dns/internal/resolver"
@@ -35,6 +38,7 @@ func (a *App) hooks() api.Hooks {
RefreshBlocklists: a.refreshBlocklists,
ToggleBlocklist: a.toggleBlocklist,
DomainCheck: a.domainCheck,
Resolve: a.resolveTest,
ListDomains: a.listDomains,
AddDomain: a.addDomain,
DeleteDomain: a.deleteDomain,
@@ -398,7 +402,60 @@ func (a *App) domainCheck(name string) (any, error) {
return out, nil
}
// listDomains pages the compiled rules. Walking a million-entry map on every
// resolveTest runs one query through the live pipeline. It goes through the
// engine rather than straight to an upstream: a test that skipped the
// pipeline would report a healthy upstream while the blocklist, the ACL or the
// local zones were what a client actually hit.
func (a *App) resolveTest(ctx context.Context, name, qtype string) (any, error) {
if a.engine == nil {
return nil, errors.New("the query engine is not running")
}
qt := dns.TypeA
if qtype = strings.TrimSpace(qtype); qtype != "" {
var ok bool
qt, ok = dns.StringToType[strings.ToUpper(qtype)]
if !ok {
return nil, fmt.Errorf("unknown record type %q", qtype)
}
}
q := new(dns.Msg)
q.SetQuestion(dns.Fqdn(name), qt)
q.RecursionDesired = true
res := a.engine.Handle(ctx, engine.Request{
Msg: q,
Remote: netip.AddrFrom4([4]byte{127, 0, 0, 1}),
Transport: "api",
Start: time.Now(),
})
out := map[string]any{
"name": dns.Fqdn(name),
"type": dns.TypeToString[qt],
"rcode": "SERVFAIL",
"action": string(res.Action),
"duration_ms": res.Duration.Milliseconds(),
"upstream": res.Upstream,
"group": res.Group,
"cache": res.CacheKind,
"local": res.Local,
"truncated": res.Truncated,
"blocked": res.BlockSource != "",
"block_source": res.BlockSource,
"answers": []string{},
}
if res.Msg == nil {
out["error"] = "no response"
return out, nil
}
out["rcode"] = dns.RcodeToString[res.Msg.Rcode]
answers := make([]string, 0, len(res.Msg.Answer))
for _, rr := range res.Msg.Answer {
answers = append(answers, strings.TrimSpace(rr.String()))
}
out["answers"] = answers
return out, nil
}
// listDomains pages the compiled rules.
// request would be too slow, so the filter runs over a bounded sample unless
// the query is a prefix/exact lookup, which the LRU can answer directly.
func (a *App) listDomains(q api.DomainQuery) (any, error) {