Cap concurrent password checks and count attempts before checking
Every argon2 run takes 64 MiB and nothing limited how many ran at once, so parallel sign-in attempts could run the server out of memory (8 at once used about 600 MB). At most two now run at once; at most 16 sign-ins wait for one, more get HTTP 429. 30 parallel sign-ins peaked at 275 MB. A sign-in attempt now counts toward the lockout before its password is checked, so parallel attempts cannot get past it; a right password takes its own attempt back. IPv6 addresses are locked out by /64.
This commit is contained in:
@@ -232,7 +232,7 @@ func (a *App) login(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
slog.Warn("login failed", "user", in.Username, "remote", ip, "reason", err.Error())
|
||||
code := http.StatusUnauthorized
|
||||
if errors.Is(err, errLocked) {
|
||||
if errors.Is(err, errLocked) || errors.Is(err, errBusy) {
|
||||
code = http.StatusTooManyRequests
|
||||
}
|
||||
writeJSON(w, code, map[string]string{"error": err.Error()})
|
||||
|
||||
Reference in New Issue
Block a user