server: canary DNS — authoritative zone with frozen §6.1 reference records
Stdlib DNS responder (no external deps): parses single-question queries
with EDNS OPT (bufsize, DO, ECS), serves the spec's frozen reference
records (ttl-{5,60,3600,86400} A/AAAA/TXT, many-rr 8×A in order, big-txt
~1800B), and per-query <nonce>.<session>.<zone> answers in 192.0.2.0/24.
UDP truncation sets TC past 512 (or the EDNS bufsize); TCP never
truncates — the EDNS-bufsize / TCP-fallback test. Every query is logged
(qname, resolver, transport, EDNS, ECS, case) and surfaced per session
prefix in GET /v1/sessions/{id}/observations as dns_canary. Profile gains
canary_zone + the canary-dns capability when configured.
Wire format validated against an independent client (correct rcodes,
answer counts, TC behavior, full EDNS response); unit tests cover
references, truncation-vs-EDNS, logging, NXDOMAIN.
Versioning: patch-first convention recorded in CLAUDE.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4f5499198b
commit
35baf70cdb
@@ -47,6 +47,10 @@ type Server struct {
|
||||
TCPRecent func(ip string) any
|
||||
// DelayedEcho schedules/sends a DELAYED_ECHO for a session (may be nil).
|
||||
DelayedEcho func(sess *session.Session, actionID string) error
|
||||
// CanaryQueries returns logged canary lookups for a session prefix (may be nil).
|
||||
CanaryQueries func(sessionPrefix string) any
|
||||
// CanaryZone is surfaced in the profile so the app knows what to query.
|
||||
CanaryZone string
|
||||
}
|
||||
|
||||
func (s *Server) Handler() http.Handler {
|
||||
@@ -93,11 +97,16 @@ func (s *Server) observations(w http.ResponseWriter, r *http.Request) {
|
||||
tcp = s.TCPRecent(sess.ControlSource.Unmap().String())
|
||||
}
|
||||
}
|
||||
var dnsCanary any
|
||||
if s.CanaryQueries != nil {
|
||||
dnsCanary = s.CanaryQueries(sess.ID[:16]) // the session's wire prefix
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"udp": map[string]any{"packets_seen": packetsSeen, "packets": udp},
|
||||
"tcp": tcp,
|
||||
"connect_back": cb,
|
||||
// TODO(spec §6): http echo records, dns_canary
|
||||
"dns_canary": dnsCanary,
|
||||
// TODO(spec §6): http echo records
|
||||
})
|
||||
}
|
||||
|
||||
@@ -243,9 +252,10 @@ func (s *Server) profile(w http.ResponseWriter, r *http.Request) {
|
||||
"tcp_port": s.TCPPort,
|
||||
"stun_port": s.StunPort,
|
||||
}},
|
||||
"pins": []string{"pin-sha256:" + s.PinB64},
|
||||
"next_pins": []string{},
|
||||
"limits": map[string]any{"max_kbps": 50000, "max_session_s": 900},
|
||||
"pins": []string{"pin-sha256:" + s.PinB64},
|
||||
"next_pins": []string{},
|
||||
"canary_zone": s.CanaryZone,
|
||||
"limits": map[string]any{"max_kbps": 50000, "max_session_s": 900},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user