Skip to content

Commit

Permalink
fixed CAA records timeout problem
Browse files Browse the repository at this point in the history
  • Loading branch information
mariuskimmina committed Aug 23, 2022
1 parent 814b6c4 commit dc25fc4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 50 deletions.
24 changes: 12 additions & 12 deletions manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (
)

type ACMEManager struct {
Config *certmagic.Config
Issuer *certmagic.ACMEIssuer
Zone string
Config *certmagic.Config
Issuer *certmagic.ACMEIssuer
Zone string
}

// NewACMEManager create a new ACMEManager
Expand All @@ -27,12 +27,12 @@ func NewACMEManager(config *dnsserver.Config, zone string, ca string, path strin
ca = "localhost:14001/dir" //pebble default
}

// default email if none is provided
// providing a reail email is recommended to receiv notifications for expiring certificates
// in case that something goes wrong
if email == "" {
email = "[email protected]"
}
// default email if none is provided
// providing a reail email is recommended to receiv notifications for expiring certificates
// in case that something goes wrong
if email == "" {
email = "[email protected]"
}

pool, err := x509.SystemCertPool()
if err != nil {
Expand All @@ -46,7 +46,7 @@ func NewACMEManager(config *dnsserver.Config, zone string, ca string, path strin
}
pemcert, _ := pem.Decode(certbytes)
if pemcert == nil {
log.Errorf("Failed to decode CaCert: %v \n", err)
log.Errorf("Failed to decode CaCert: %v \n", err)
}
cert, err := x509.ParseCertificate(pemcert.Bytes)
if err != nil {
Expand All @@ -57,7 +57,7 @@ func NewACMEManager(config *dnsserver.Config, zone string, ca string, path strin

readyChan := make(chan string)
solver := &DNSSolver{
Port: port,
Port: port,
readyChan: readyChan,
}

Expand Down Expand Up @@ -104,7 +104,7 @@ func (am *ACMEManager) configureTLSwithACME(ctx context.Context) (*tls.Config, *
// try loading existing certificate
cert, err = am.Config.CacheManagedCertificate(ctx, am.Zone)
if err != nil {
log.Info("Obtaining TLS Certificate")
log.Info("Obtaining TLS Certificate, may take a moment")
if !errors.Is(err, fs.ErrNotExist) {
return nil, nil, err
}
Expand Down
39 changes: 19 additions & 20 deletions setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ var (
)

const (
argDomain = "domain"
argCheckInternal = "checkinterval"
argCa = "ca"
argCaCert = "cacert"
argEmail = "email"
argCertPath = "certpath"
argPort = "port"
argDomain = "domain"
argCheckInternal = "checkinterval"
argCa = "ca"
argCaCert = "cacert"
argEmail = "email"
argCertPath = "certpath"
argPort = "port"
)

func parseTLS(c *caddy.Controller) error {
Expand Down Expand Up @@ -70,8 +70,8 @@ func parseTLS(c *caddy.Controller) error {
var ca string
var caCert string
var port string
var email string
checkInterval := 15
var email string
checkInterval := 15
userHome, homeExists := os.LookupEnv("HOME")
if !homeExists {
log.Error("Environment Variable $HOME needs to be set.")
Expand Down Expand Up @@ -122,19 +122,18 @@ func parseTLS(c *caddy.Controller) error {
if len(checkIntervalArgs) > 1 {
return plugin.Error("tls", c.Errf("Too many arguments to checkInterval"))
}
interval, err := strconv.Atoi(checkIntervalArgs[0])
if err != nil {
return plugin.Error("Failed to convert checkInterval argument to integer: %v \n", err)
}
checkInterval = interval
interval, err := strconv.Atoi(checkIntervalArgs[0])
if err != nil {
return plugin.Error("Failed to convert checkInterval argument to integer: %v \n", err)
}
checkInterval = interval
default:
return c.Errf("unknown argument to acme '%s'", token)
}
}


// the ACME DNS-01 Challenge doesn't work with other ports than 53
// this option is really only there to use in tests with Pebble
// the ACME DNS-01 Challenge doesn't work with other ports than 53
// this option is really only there to use in tests with Pebble
portNumber := 53
if port != "" {
portNumber, err = strconv.Atoi(port)
Expand All @@ -149,9 +148,9 @@ func parseTLS(c *caddy.Controller) error {
names = append(names, manager.Zone)

tlsconf, cert, err = manager.configureTLSwithACME(ctx)
if err != nil {
log.Errorf("Failed to setup TLS automatically: %v \n", err)
}
if err != nil {
log.Errorf("Failed to setup TLS automatically: %v \n", err)
}
config.TLSConfig = tlsconf

once.Do(func() {
Expand Down
28 changes: 11 additions & 17 deletions solver.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ import (

// DNSSolver is minimal dns.Server that can solve the ACME Challenge
type DNSSolver struct {
Port int
Port int
m sync.Mutex
server *dns.Server
readyChan chan string
}


// Start starts a dns.Server that can solve the ACME Challenge, which means it answer on TXT requests
// that start with _acme-challenge - this server will ignore all other requests
func (ds *DNSSolver) Start(p net.PacketConn, challenge acme.Challenge) error {
Expand All @@ -31,16 +30,13 @@ func (ds *DNSSolver) Start(p net.PacketConn, challenge acme.Challenge) error {
state := request.Request{W: w, Req: r}

log.Debugf("Received DNS request | name: %s, type: %s, source ip: %s \n", state.Name(), state.Type(), state.IP())
hdr := dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeTXT, Class: dns.ClassANY, Ttl: 0}
m := new(dns.Msg)
m.SetReply(r)

//if state.QType() == dns.TypeCAA {
//log.Debug("Answering CAA request:", state.Name())
//m.Answer = append(m.Answer, &dns.CAA{Hdr: hdr, Value: "letsencrypt.org"})
//w.WriteMsg(m)
//return
//}
if state.QType() == dns.TypeCAA {
hdr := dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeCAA, Class: dns.ClassANY, Ttl: 0}
m.Answer = append(m.Answer, &dns.CAA{Hdr: hdr})
}

if state.QType() != dns.TypeTXT {
acme_request = false
Expand All @@ -50,13 +46,11 @@ func (ds *DNSSolver) Start(p net.PacketConn, challenge acme.Challenge) error {
acme_request = false
}

if !acme_request {
log.Debugf("Ignoring DNS request name: %s\n", state.Name())
return
if acme_request {
log.Info("Answering ACME DNS request:", state.Name())
hdr := dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeTXT, Class: dns.ClassANY, Ttl: 0}
m.Answer = append(m.Answer, &dns.TXT{Hdr: hdr, Txt: []string{challenge.DNS01KeyAuthorization()}})
}

log.Info("Answering DNS request:", state.Name())
m.Answer = append(m.Answer, &dns.TXT{Hdr: hdr, Txt: []string{challenge.DNS01KeyAuthorization()}})
w.WriteMsg(m)
return
})}
Expand Down Expand Up @@ -95,14 +89,14 @@ func (ds *DNSSolver) Present(ctx context.Context, challenge acme.Challenge) erro

l, err := net.ListenUDP("udp", &addr)
if err != nil {
log.Errorf("Failed to create Listener: %v \n", err)
log.Errorf("Failed to create Listener: %v \n", err)
}

go func() {
// start a dns.server that runs in a seperate goroutine
err := ds.Start(l, challenge)
if err != nil {
log.Errorf("Failed to start DNS Server for ACME Challenge: %v \n", err)
log.Errorf("Failed to start DNS Server for ACME Challenge: %v \n", err)
}
}()
return nil
Expand Down
2 changes: 1 addition & 1 deletion solver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func setupACME(readyChan chan string) {
acmeServer := &DNSSolver{
Port: 2053,
Port: 2053,
readyChan: readyChan,
}
addr := net.UDPAddr{
Expand Down

0 comments on commit dc25fc4

Please sign in to comment.