mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
fix: ensure upstream health checks can handle large DNS responses
- Add UpstreamConfig.VerifyMsg() method with proper EDNS0 support - Replace hardcoded DNS messages in health checks with standardized verification method - Set EDNS0 buffer size to 4096 bytes to handle large DNS responses - Add test case for legacy resolver with extensive extra sections
This commit is contained in:
committed by
Cuong Manh Le
parent
d71d1341b6
commit
fd48e6d795
@@ -1400,9 +1400,6 @@ func (p *prog) checkUpstreamOnce(upstream string, uc *ctrld.UpstreamConfig) erro
|
||||
return err
|
||||
}
|
||||
|
||||
msg := new(dns.Msg)
|
||||
msg.SetQuestion(".", dns.TypeNS)
|
||||
|
||||
timeout := 1000 * time.Millisecond
|
||||
if uc.Timeout > 0 {
|
||||
timeout = time.Millisecond * time.Duration(uc.Timeout)
|
||||
@@ -1416,6 +1413,7 @@ func (p *prog) checkUpstreamOnce(upstream string, uc *ctrld.UpstreamConfig) erro
|
||||
mainLog.Load().Debug().Msgf("Rebootstrapping resolver for upstream: %s", upstream)
|
||||
|
||||
start := time.Now()
|
||||
msg := uc.VerifyMsg()
|
||||
_, err = resolver.Resolve(ctx, msg)
|
||||
duration := time.Since(start)
|
||||
|
||||
|
||||
@@ -358,6 +358,15 @@ func (uc *UpstreamConfig) Init() {
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyMsg creates and returns a new DNS message could be used for testing upstream health.
|
||||
func (uc *UpstreamConfig) VerifyMsg() *dns.Msg {
|
||||
msg := new(dns.Msg)
|
||||
msg.RecursionDesired = true
|
||||
msg.SetQuestion(".", dns.TypeNS)
|
||||
msg.SetEdns0(4096, false) // ensure handling of large DNS response
|
||||
return msg
|
||||
}
|
||||
|
||||
// VerifyDomain returns the domain name that could be resolved by the upstream endpoint.
|
||||
// It returns empty for non-ControlD upstream endpoint.
|
||||
func (uc *UpstreamConfig) VerifyDomain() string {
|
||||
|
||||
@@ -120,8 +120,7 @@ func (p *ptrDiscover) lookupIPByHostname(name string, v6 bool) string {
|
||||
// is reachable, set p.serverDown to false, so p.lookupHostname can continue working.
|
||||
func (p *ptrDiscover) checkServer() {
|
||||
bo := backoff.NewBackoff("ptrDiscover", func(format string, args ...any) {}, time.Minute*5)
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(".", dns.TypeNS)
|
||||
m := (&ctrld.UpstreamConfig{}).VerifyMsg()
|
||||
ping := func() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -282,6 +282,35 @@ func Test_Edns0_CacheReply(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Control-D-Inc/ctrld/issues/255
|
||||
func Test_legacyResolverWithBigExtraSection(t *testing.T) {
|
||||
lanPC, err := net.ListenPacket("udp", "127.0.0.1:0") // 127.0.0.1 is considered LAN (loopback)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to listen on LAN address: %v", err)
|
||||
}
|
||||
lanServer, lanAddr, err := runLocalPacketConnTestServer(t, lanPC, bigExtraSectionHandler())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to run LAN test server: %v", err)
|
||||
}
|
||||
defer lanServer.Shutdown()
|
||||
|
||||
uc := &UpstreamConfig{
|
||||
Name: "Legacy",
|
||||
Type: ResolverTypeLegacy,
|
||||
Endpoint: lanAddr,
|
||||
}
|
||||
uc.Init()
|
||||
r, err := NewResolver(uc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = r.Resolve(context.Background(), uc.VerifyMsg())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_upstreamTypeFromEndpoint(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -370,6 +399,68 @@ func countHandler(call *atomic.Int64) dns.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func mustRR(s string) dns.RR {
|
||||
r, err := dns.NewRR(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func bigExtraSectionHandler() dns.HandlerFunc {
|
||||
return func(w dns.ResponseWriter, msg *dns.Msg) {
|
||||
m := &dns.Msg{
|
||||
Answer: []dns.RR{
|
||||
mustRR(". 7149 IN NS m.root-servers.net."),
|
||||
mustRR(". 7149 IN NS c.root-servers.net."),
|
||||
mustRR(". 7149 IN NS e.root-servers.net."),
|
||||
mustRR(". 7149 IN NS j.root-servers.net."),
|
||||
mustRR(". 7149 IN NS g.root-servers.net."),
|
||||
mustRR(". 7149 IN NS k.root-servers.net."),
|
||||
mustRR(". 7149 IN NS l.root-servers.net."),
|
||||
mustRR(". 7149 IN NS d.root-servers.net."),
|
||||
mustRR(". 7149 IN NS h.root-servers.net."),
|
||||
mustRR(". 7149 IN NS b.root-servers.net."),
|
||||
mustRR(". 7149 IN NS a.root-servers.net."),
|
||||
mustRR(". 7149 IN NS f.root-servers.net."),
|
||||
mustRR(". 7149 IN NS i.root-servers.net."),
|
||||
},
|
||||
Extra: []dns.RR{
|
||||
mustRR("m.root-servers.net. 656 IN A 202.12.27.33"),
|
||||
mustRR("m.root-servers.net. 656 IN AAAA 2001:dc3::35"),
|
||||
mustRR("c.root-servers.net. 656 IN A 192.33.4.12"),
|
||||
mustRR("c.root-servers.net. 656 IN AAAA 2001:500:2::c"),
|
||||
mustRR("e.root-servers.net. 656 IN A 192.203.230.10"),
|
||||
mustRR("e.root-servers.net. 656 IN AAAA 2001:500:a8::e"),
|
||||
mustRR("j.root-servers.net. 656 IN A 192.58.128.30"),
|
||||
mustRR("j.root-servers.net. 656 IN AAAA 2001:503:c27::2:30"),
|
||||
mustRR("g.root-servers.net. 656 IN A 192.112.36.4"),
|
||||
mustRR("g.root-servers.net. 656 IN AAAA 2001:500:12::d0d"),
|
||||
mustRR("k.root-servers.net. 656 IN A 193.0.14.129"),
|
||||
mustRR("k.root-servers.net. 656 IN AAAA 2001:7fd::1"),
|
||||
mustRR("l.root-servers.net. 656 IN A 199.7.83.42"),
|
||||
mustRR("l.root-servers.net. 656 IN AAAA 2001:500:9f::42"),
|
||||
mustRR("d.root-servers.net. 656 IN A 199.7.91.13"),
|
||||
mustRR("d.root-servers.net. 656 IN AAAA 2001:500:2d::d"),
|
||||
mustRR("h.root-servers.net. 656 IN A 198.97.190.53"),
|
||||
mustRR("h.root-servers.net. 656 IN AAAA 2001:500:1::53"),
|
||||
mustRR("b.root-servers.net. 656 IN A 170.247.170.2"),
|
||||
mustRR("b.root-servers.net. 656 IN AAAA 2801:1b8:10::b"),
|
||||
mustRR("a.root-servers.net. 656 IN A 198.41.0.4"),
|
||||
mustRR("a.root-servers.net. 656 IN AAAA 2001:503:ba3e::2:30"),
|
||||
mustRR("f.root-servers.net. 656 IN A 192.5.5.241"),
|
||||
mustRR("f.root-servers.net. 656 IN AAAA 2001:500:2f::f"),
|
||||
mustRR("i.root-servers.net. 656 IN A 192.36.148.17"),
|
||||
mustRR("i.root-servers.net. 656 IN AAAA 2001:7fe::53"),
|
||||
},
|
||||
}
|
||||
|
||||
m.Compress = true
|
||||
m.SetReply(msg)
|
||||
w.WriteMsg(m)
|
||||
}
|
||||
}
|
||||
|
||||
func generateEdns0ClientCookie() string {
|
||||
cookie := make([]byte, 8)
|
||||
if _, err := rand.Read(cookie); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user