aboutsummaryrefslogtreecommitdiff
path: root/backend/admin.go
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2025-12-26 23:15:06 +0100
committerAnhgelus Morhtuuzh <william@herges.fr>2025-12-26 23:15:06 +0100
commit563494cb7779a840bd650f0cf215b6e6ae7080ed (patch)
tree8a2630444cbfbbe6db9c073450467eeb01e028cd /backend/admin.go
parentaf11793ca48244eafd7dcdf66ac1dff83995a775 (diff)
feat(backend): introduce rate limit to protect auth
Diffstat (limited to 'backend/admin.go')
-rw-r--r--backend/admin.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/backend/admin.go b/backend/admin.go
index 9cb5376..e5f5696 100644
--- a/backend/admin.go
+++ b/backend/admin.go
@@ -1,8 +1,13 @@
package backend
import (
+ "context"
+ "math"
"net/http"
"strconv"
+ "strings"
+ "sync"
+ "time"
"git.anhgelus.world/anhgelus/small-web/backend/storage"
"github.com/go-chi/chi/v5"
@@ -16,6 +21,64 @@ type adminData struct {
CurrentPage int
}
+type to struct {
+ n int
+ since time.Time
+}
+
+type tos struct {
+ mu sync.Mutex
+ tos map[string]*to
+}
+
+var timeouts = tos{tos: make(map[string]*to)}
+
+func handleTimeout(ctx context.Context) bool {
+ ip := ctx.Value(ipAdressKey).(string)
+ parsed := strings.Split(ip, ":")
+ ip = parsed[0]
+
+ timeouts.mu.Lock()
+ defer timeouts.mu.Unlock()
+
+ v, ok := timeouts.tos[ip]
+ if !ok {
+ timeouts.tos[ip] = &to{n: 1}
+ return false
+ }
+ dur := func() time.Duration { return time.Duration(math.Pow10(v.n/4)) * time.Second }
+ if time.Since(v.since) <= dur() {
+ return true
+ }
+ v.n++
+ if v.n%4 != 0 {
+ return false
+ }
+ v.since = time.Now()
+ GetLogger(ctx).Warn("rate limiting IP", "ip", ip, "duration", dur().String())
+ go func(v *to) {
+ time.Sleep(3 * time.Hour)
+ v.n = max(v.n-4, 0)
+ }(v)
+ return true
+}
+
+func resetTimeout(ctx context.Context) {
+ ip := ctx.Value(ipAdressKey).(string)
+ parsed := strings.Split(ip, ":")
+ ip = parsed[0]
+
+ timeouts.mu.Lock()
+ defer timeouts.mu.Unlock()
+
+ v, ok := timeouts.tos[ip]
+ if !ok {
+ return
+ }
+ v.n = 0
+ v.since = time.Unix(0, 0)
+}
+
func HandleAdmin(r *chi.Mux) {
r.Get("/admin", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()