From c286b3b1d0a21bc5cc447df7744da9894d857e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Leopoldo=20Sologuren=20Guti=C3=A9rrez?= Date: Wed, 4 Jan 2023 05:26:14 +0000 Subject: [PATCH] Added TokenBucket to limit the rate of validation failures (#151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added new TockenBucket named `acmeClientFailLimit` to avoid being banned because of the [Failed validation limit](https://letsencrypt.org/docs/failed-validation-limit/) of Let's Encrypt. The behaviour is similar to the other limiters blocking the `obtainCert` func ensuring rate under limit. Co-authored-by: fsologureng Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://codeberg.org/Codeberg/pages-server/pulls/151 Reviewed-by: 6543 <6543@obermui.de> Co-authored-by: Felipe Leopoldo Sologuren GutiƩrrez Co-committed-by: Felipe Leopoldo Sologuren GutiƩrrez --- server/certificates/certificates.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/certificates/certificates.go b/server/certificates/certificates.go index e3cdbfb..1aa90a0 100644 --- a/server/certificates/certificates.go +++ b/server/certificates/certificates.go @@ -163,6 +163,9 @@ var acmeClientOrderLimit = equalizer.NewTokenBucket(25, 15*time.Minute) // rate limit is 20 / second, we want 5 / second (especially as one cert takes at least two requests) var acmeClientRequestLimit = equalizer.NewTokenBucket(5, 1*time.Second) +// rate limit is 5 / hour https://letsencrypt.org/docs/failed-validation-limit/ +var acmeClientFailLimit = equalizer.NewTokenBucket(5, 1*time.Hour) + type AcmeTLSChallengeProvider struct { challengeCache cache.SetGetKey } @@ -278,6 +281,9 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re res, err = acmeClient.Certificate.Renew(*renew, true, false, "") if err != nil { log.Error().Err(err).Msgf("Couldn't renew certificate for %v, trying to request a new one", domains) + if acmeUseRateLimits { + acmeClientFailLimit.Take() + } res = nil } } @@ -298,6 +304,9 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re Bundle: true, MustStaple: false, }) + if acmeUseRateLimits && err != nil { + acmeClientFailLimit.Take() + } } if err != nil { log.Error().Err(err).Msgf("Couldn't obtain again a certificate or %v", domains)