diff options
author | Jaime Martinez <jmartinez@gitlab.com> | 2021-09-22 09:38:25 +0300 |
---|---|---|
committer | Jaime Martinez <jmartinez@gitlab.com> | 2021-10-14 08:59:51 +0300 |
commit | ccfdff303646b86daed2bd9ae7e2f2a5eb4a2c5c (patch) | |
tree | 81bc3444ad0417cd4454077fd187323a292bfc93 /app.go | |
parent | 247bd7ba2fd9139711218c6a42ed03c551f958d9 (diff) |
feat: add source IP ratelimiter middleware
It gets the source IP from `r.RemoteAddr` or from the `X-Forwarded-For`
header for proxied requests (when `--listen-proxy` is enabled).
The first iteration will only report logs and metrics when an IP is
being rate limited.
The rate limiter uses a Token Bucket approach using
golang.org/x/time/rate, which can be configured with the newly added
flags `rate-limit-source-ip` and `rate-limit-source-ip-burst`.
To enable the rate limiter, set `rate-limit-source-ip` to value > 1,
which is the number of requests per second to allow. It is enabled by
default in "dry-run" mode so requests won't be dropped until the
environment variable
`FF_ENABLE_RATE_LIMITER` is set to `"true"`.
See metrics.go for the newly added metrics.
Changelog: added
Diffstat (limited to 'app.go')
-rw-r--r-- | app.go | 11 |
1 files changed, 11 insertions, 0 deletions
@@ -32,6 +32,7 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors" "gitlab.com/gitlab-org/gitlab-pages/internal/logging" "gitlab.com/gitlab-org/gitlab-pages/internal/netutil" + "gitlab.com/gitlab-org/gitlab-pages/internal/ratelimiter" "gitlab.com/gitlab-org/gitlab-pages/internal/rejectmethods" "gitlab.com/gitlab-org/gitlab-pages/internal/request" "gitlab.com/gitlab-org/gitlab-pages/internal/routing" @@ -262,6 +263,16 @@ func (a *theApp) buildHandlerPipeline() (http.Handler, error) { handler = routing.NewMiddleware(handler, a.source) + if a.config.RateLimit.SourceIPLimitPerSecond > 0 { + rl := ratelimiter.New( + ratelimiter.WithSourceIPLimitPerSecond(a.config.RateLimit.SourceIPLimitPerSecond), + ratelimiter.WithSourceIPBurstSize(a.config.RateLimit.SourceIPBurst), + ratelimiter.WithProxied(len(a.config.Listeners.Proxy) > 0), + ) + + handler = rl.SourceIPLimiter(handler) + } + // Health Check handler, err = a.healthCheckMiddleware(handler) if err != nil { |