Skip to content

Commit

Permalink
feat: custom dns resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
fritterhoff committed Oct 1, 2024
1 parent 9fbba94 commit 0005ad9
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 2 deletions.
4 changes: 3 additions & 1 deletion acme/challenge.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (ch *Challenge) ToLog() (interface{}, error) {
// 'validated' attributes are updated.
func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey, payload []byte) error {
// If already valid or invalid then return without performing validation.
if ch.Status != StatusPending {
if ch.Status != StatusPending && ch.Status != StatusInvalid {
return nil
}
switch ch.Type {
Expand Down Expand Up @@ -402,6 +402,7 @@ func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebK
vc := MustClientFromContext(ctx)
txtRecords, err := vc.LookupTxt(dns01ChallengeHost(domain))
if err != nil {
logrus.Warnf("error looking up TXT records for domain %s: %v", domain, err)
return storeError(ctx, db, ch, false, WrapError(ErrorDNSType, err,
"error looking up TXT records for domain %s", domain))
}
Expand Down Expand Up @@ -1611,6 +1612,7 @@ func KeyAuthorization(token string, jwk *jose.JSONWebKey) (string, error) {
func storeError(ctx context.Context, db DB, ch *Challenge, markInvalid bool, err *Error) error {
ch.Error = err
if markInvalid {
logrus.Warnf("marking challenge %s as invalid: %v", ch.ID, err)
ch.Status = StatusInvalid
}
if err := db.UpdateChallenge(ctx, ch); err != nil {
Expand Down
101 changes: 100 additions & 1 deletion acme/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ package acme
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"os"
"time"

"github.com/miekg/dns"
"github.com/sirupsen/logrus"
)

// Client is the interface used to verify ACME challenges.
Expand Down Expand Up @@ -72,8 +77,102 @@ func (c *client) Get(url string) (*http.Response, error) {
return c.http.Get(url)
}

var timeouts [5]time.Duration = [5]time.Duration{(time.Second * 1), (time.Second * 1), (time.Second * 2), (time.Second * 4), (time.Second * 2)}

func ResolveWithTimeout(name, resolver string, qtype, qclass uint16) (*dns.Msg, error) {
client := new(dns.Client)
msg := &dns.Msg{
MsgHdr: dns.MsgHdr{
Id: dns.Id(),
RecursionDesired: true,
},
Question: []dns.Question{{Name: dns.Fqdn(name), Qtype: qtype, Qclass: qclass}},
}
msg.AuthenticatedData = true
msg.SetEdns0(4096, true)

for i := 0; i < len(timeouts); i++ {

client.Timeout = timeouts[i]
resp, _, err := client.Exchange(msg, fmt.Sprintf("%s:53", resolver))
if err == nil && resp.Truncated {
tcpConn, _ := dns.Dial("tcp", fmt.Sprintf("%s:53", resolver))
resp, _, err = client.ExchangeWithConn(msg, tcpConn)
}
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
logrus.Warnf("Timeout querying %s records '%s' after %v", dns.TypeToString[qtype], name, timeouts[i])
continue
}
return nil, err
}

return resp, nil

}
return nil, &net.DNSError{
Name: name,
Err: "Final timeout.",
IsTimeout: true,
}
}

func LookupTxt(name, resolver string) ([]string, error) {
logrus.Infof("Using custom resolver %s for lookup of %s", resolver, name)
resp, err := ResolveWithTimeout(name, resolver, dns.TypeTXT, dns.ClassINET)
if err != nil {
logrus.Warnf("Failed to lookup %s: %v", name, err)
return nil, err
}
nsData := []string{}
data := []string{}

// Check if TXT records are present
for _, answer := range resp.Answer {
if txt, ok := answer.(*dns.TXT); ok {
logrus.Infof("Resolved TXT records for %s: %s", name, txt.Txt)
data = append(data, txt.Txt...)
}
}
if len(data) > 0 {
return data, nil
}
resp, err = ResolveWithTimeout(name, resolver, dns.TypeCNAME, dns.ClassINET)
if err != nil {
logrus.Warnf("Failed to lookup %s: %v", name, err)
return nil, err
}
// Check if CNAME records are present
for _, answer := range resp.Answer {
if cname, ok := answer.(*dns.CNAME); ok {
logrus.Infof("Resolved CNAME records for %s: %s", name, cname.Target)
// Get NS records for the CNAME
resp, err := ResolveWithTimeout(cname.Target, resolver, dns.TypeSOA, dns.ClassINET)
if err != nil {
logrus.Warnf("Failed to lookup %s: %v", cname.Target, err)
continue
}
for _, answer := range resp.Ns {
if ns, ok := answer.(*dns.SOA); ok {
logrus.Infof("Resolved NS records for %s: %s", cname.Target, ns.Ns)
nsData = append(nsData, ns.Ns)
}
}
for _, ns := range nsData {
logrus.Infof("Resolving %s using %s", cname.Target, ns)
return LookupTxt(cname.Target, ns)
}
}
}

return data, nil
}
func (c *client) LookupTxt(name string) ([]string, error) {
return net.LookupTXT(name)
resolver := os.Getenv("DNS_RESOLVER")
if resolver != "" {
return LookupTxt(name, resolver)
}
return c.LookupTxt(name)
}

func (c *client) TLSDial(network, addr string, config *tls.Config) (*tls.Conn, error) {
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,13 @@ require (
go.opentelemetry.io/otel/metric v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/time v0.6.0 // indirect
golang.org/x/tools v0.24.0 // indirect
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
Expand All @@ -195,4 +197,5 @@ replace github.com/smallstep/nosql => github.com/hm-edu/nosql v0.4.1-0.202405061
require (
github.com/eclipse/paho.mqtt.golang v1.4.3
github.com/gorilla/websocket v1.5.0 // indirect
github.com/miekg/dns v1.1.61
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
Expand Down Expand Up @@ -585,6 +587,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -686,6 +690,8 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down

0 comments on commit 0005ad9

Please sign in to comment.