Skip to content

Commit 0791210

Browse files
committed
Retry over TCP if TC bit is set for DNS TXT records and set EDNS0
TXT records can be quite large, with is a problem for DNS challenges, they don't fit in the 512 buffer especially if there are multiple. DNS servers can increase the buffer size through EDNS0 extension, and retry over TCP if that wasn't enough. DNS server should truncate response if it doesn't fit in the buffer, and set TC (Truncate) bit, then DNS client should retry over TCP. 1220 value for UDP buffer size was chosen based on this recommendation: https://www.isc.org/blogs/dns-flag-day-2020-2/ This changes only TXT request, I left other methods untouched. But it would make sense to do the same logic for all requests, by building some small abstraction around miekg/dns for requests. Also see docs for Exchange function: https://pkg.go.dev/github.com/miekg/dns#Client.Exchange Was originally found in #536 (comment)
1 parent d180fbf commit 0791210

1 file changed

Lines changed: 13 additions & 0 deletions

File tree

va/va.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ type VAImpl struct {
111111
strict bool
112112
customResolverAddr string
113113
dnsClient *dns.Client
114+
dnsClientTCP *dns.Client
114115

115116
// The VA having a DB client is indeed strange. This is only used to
116117
// facilitate va.setOrderError changing the ARI related order replacement
@@ -139,6 +140,8 @@ func New(
139140
if customResolverAddr != "" {
140141
va.log.Printf("Using custom DNS resolver for ACME challenges: %s", customResolverAddr)
141142
va.dnsClient = new(dns.Client)
143+
va.dnsClientTCP = new(dns.Client)
144+
va.dnsClientTCP.Net = "tcp"
142145
} else {
143146
va.log.Print("Using system DNS resolver for ACME challenges")
144147
}
@@ -832,10 +835,20 @@ func (va VAImpl) getTXTEntry(name string) ([]string, error) {
832835
return net.DefaultResolver.LookupTXT(ctx, name)
833836
}
834837

838+
const dnssec = false
839+
const udpMaxMsgSize uint16 = 1220 // should be small enough to not cause packet fragmentation
840+
835841
var txts []string
836842
message := new(dns.Msg)
837843
message.SetQuestion(dns.Fqdn(name), dns.TypeTXT)
844+
message.SetEdns0(udpMaxMsgSize, dnssec)
838845
in, _, err := va.dnsClient.ExchangeContext(ctx, message, va.customResolverAddr)
846+
847+
if in.Truncated {
848+
// Response was truncated, retry over TCP instead
849+
in, _, err = va.dnsClientTCP.ExchangeContext(ctx, message, va.customResolverAddr)
850+
}
851+
839852
if err != nil {
840853
return nil, err
841854
}

0 commit comments

Comments
 (0)