{"record":{"id":"f37142aa4ace1abf","repo":"TechnitiumSoftware/DnsServer","slug":"max-limit-of-max-login-attempts-attempts-exceede","errorCode":null,"errorMessage":"Max limit of {MAX_LOGIN_ATTEMPTS} attempts exceeded. Access blocked for {BLOCK_NETWORK_INTERVAL / 1000} seconds.","messagePattern":"Max limit of (.+?) attempts exceeded\\. Access blocked for (.+?) seconds\\.","errorType":"exception","errorClass":"DnsWebServiceException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Auth/AuthManager.cs","lineNumber":786,"sourceCode":"                    _log.Write(ex);\n\n                    adminUser = CreateUser(\"Administrator\", \"admin\", \"admin\");\n                }\n            }\n            else\n            {\n                adminUser = CreateUser(\"Administrator\", \"admin\", \"admin\");\n            }\n\n            adminUser.AddToGroup(adminGroup);\n        }\n\n        private async Task<User> AuthenticateUserAsync(string username, string password, string totp, IPAddress remoteAddress)\n        {\n            IPAddress network = GetClientNetwork(remoteAddress);\n\n            if (IsNetworkBlocked(network))\n                throw new DnsWebServiceException(\"Max limit of \" + MAX_LOGIN_ATTEMPTS + \" attempts exceeded. Access blocked for \" + (BLOCK_NETWORK_INTERVAL / 1000) + \" seconds.\");\n\n            User user = GetUser(username);\n\n            if ((user is null) || user.IsSsoUser || !user.PasswordHash.Equals(user.GetPasswordHashFor(password), StringComparison.Ordinal))\n            {\n                if ((username != \"admin\") || (password != \"admin\"))\n                {\n                    MarkFailedLoginAttempt(network);\n\n                    if (HasLoginAttemptExceedLimit(network, MAX_LOGIN_ATTEMPTS))\n                        BlockNetwork(network, BLOCK_NETWORK_INTERVAL);\n                }\n\n                await Task.Delay(1000);\n\n                throw new DnsWebServiceException(\"Invalid username or password for user: \" + username);\n            }\n","sourceCodeStart":768,"sourceCodeEnd":804,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Auth/AuthManager.cs#L768-L804","documentation":"Thrown as DnsWebServiceException from AuthenticateUserAsync when IsNetworkBlocked returns true for the client's /32 (IPv4) or /128 (IPv6) network. After 5 failed logins (MAX_LOGIN_ATTEMPTS) the source network is blocked for 300 seconds (BLOCK_NETWORK_INTERVAL = 5*60*1000 ms). The message interpolates both constants so it reads '...5 attempts...300 seconds.' It is returned over the API as HTTP 200 with status 'error'.","triggerScenarios":"Any login attempt (POST /api/user/login) from an IP whose network is in _blockedNetworks because it previously hit 5 failed attempts. The check happens before credential validation, so even a correct password is rejected while the block is active.","commonSituations":"An admin fat-fingered the password 5 times; an automated script/monitor retries bad credentials; a NAT/shared IP aggregates many clients so one client's failures block all; the 300s window has not elapsed yet.","solutions":["Wait 300 seconds (5 minutes) for the block to expire, then retry with correct credentials.","Log in from a different source IP/network that is not blocked.","Have an admin remove the block by restarting the service (blocks are in-memory) or correcting the credentials of the failing automation immediately.","Fix the automation/monitor that is generating the failed attempts so it stops re-triggering the block."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// No pre-call API to read block state; the only 'validation' is honoring the backoff.\n// Do not hammer login; back off for 300s after repeated failures.","typeGuard":null,"tryCatchPattern":"// In HttpApiClient-style code:\ntry { await client.LoginAsync(user, pass); }\ncatch (HttpApiClientException ex) when (ex.Message.Contains(\"Access blocked\"))\n{\n    await Task.Delay(TimeSpan.FromSeconds(310)); // BLOCK_NETWORK_INTERVAL (300s) + margin\n    await client.LoginAsync(user, pass);\n}","preventionTips":["Cache valid session tokens/tokens to avoid repeated logins.","Stop retrying bad credentials; each failure counts toward the 5-attempt block.","Remember NAT'd offices share one network block, so coordinate password resets."],"tags":["auth","login","rate-limiting","network"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}