From eae4513b96f8a8fcf2dffff5ea4cc4345c845be1 Mon Sep 17 00:00:00 2001 From: Moritz Marquardt Date: Sat, 20 Nov 2021 21:39:40 +0100 Subject: [PATCH] Fix timeout for HTTP-01, bug in HTTP challenge response & only count domains towards user limit after acquiring locks --- certificates.go | 21 +++++++++++---------- main.go | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/certificates.go b/certificates.go index e5aca5c..0f75c53 100644 --- a/certificates.go +++ b/certificates.go @@ -95,12 +95,7 @@ var tlsConfig = &tls.Config{ return nil, errors.New("won't request certificate for main domain, something really bad has happened") } - err = CheckUserLimit(targetOwner) - if err != nil { - return nil, err - } - - tlsCertificate, err = obtainCert(acmeClient, []string{sni}, nil) + tlsCertificate, err = obtainCert(acmeClient, []string{sni}, nil, targetOwner) if err != nil { return nil, err } @@ -241,7 +236,7 @@ func retrieveCertFromDB(sni []byte) (tls.Certificate, bool) { // renew certificates 7 days before they expire if !tlsCertificate.Leaf.NotAfter.After(time.Now().Add(-7 * 24 * time.Hour)) { go (func() { - tlsCertificate, err = obtainCert(acmeClient, []string{string(sni)}, res) + tlsCertificate, err = obtainCert(acmeClient, []string{string(sni)}, res, "") if err != nil { log.Printf("Couldn't renew certificate for %s: %s", sni, err) } @@ -253,7 +248,7 @@ func retrieveCertFromDB(sni []byte) (tls.Certificate, bool) { } var obtainLocks = sync.Map{} -func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Resource) (tls.Certificate, error) { +func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Resource, user string) (tls.Certificate, error) { name := strings.TrimPrefix(domains[0], "*") if os.Getenv("DNS_PROVIDER") == "" && len(domains[0]) > 0 && domains[0][0] == '*' { domains = domains[1:] @@ -284,6 +279,12 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re log.Printf("Renewing certificate for %v", domains) res, err = acmeClient.Certificate.Renew(*renew, true, false, "") } else { + if user != "" { + if err := CheckUserLimit(user); err != nil { + return tls.Certificate{}, err + } + } + if os.Getenv("ACME_USE_RATE_LIMITS") != "false" { acmeClientOrderLimit.Take() acmeClientRequestLimit.Take() @@ -422,7 +423,7 @@ func setupCertificates() { // key database is not working panic(err) } else if resBytes == nil { - _, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(MainDomainSuffix), string(MainDomainSuffix[1:])}, nil) + _, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(MainDomainSuffix), string(MainDomainSuffix[1:])}, nil, "") if err != nil { log.Fatalf("Couldn't renew certificate for *%s: %s", MainDomainSuffix, err) } @@ -495,7 +496,7 @@ func setupCertificates() { // renew main certificate 30 days before it expires if !tlsCertificates[0].NotAfter.After(time.Now().Add(-30 * 24 * time.Hour)) { go (func() { - _, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(MainDomainSuffix), string(MainDomainSuffix[1:])}, res) + _, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(MainDomainSuffix), string(MainDomainSuffix[1:])}, res, "") if err != nil { log.Printf("Couldn't renew certificate for *%s: %s", MainDomainSuffix, err) } diff --git a/main.go b/main.go index c181977..700241a 100644 --- a/main.go +++ b/main.go @@ -91,7 +91,7 @@ func main() { MaxRequestBodySize: 0, NoDefaultServerHeader: true, NoDefaultDate: true, - ReadTimeout: 10 * time.Second, + ReadTimeout: 30 * time.Second, // needs to be this high for ACME certificates with ZeroSSL & HTTP-01 challenge Concurrency: 1024 * 32, // TODO: adjust bottlenecks for best performance with Gitea! MaxConnsPerIP: 100, } @@ -110,7 +110,7 @@ func main() { err := fasthttp.ListenAndServe("[::]:80", func(ctx *fasthttp.RequestCtx) { if bytes.HasPrefix(ctx.Path(), challengePath) { challenge, ok := challengeCache.Get(string(TrimHostPort(ctx.Host())) + "/" + string(bytes.TrimPrefix(ctx.Path(), challengePath))) - if !ok { + if !ok || challenge == nil { ctx.SetStatusCode(http.StatusNotFound) ctx.SetBodyString("no challenge for this token") }