Brute-force protection Node.js examples

Roman Voloboev
3 min readJan 30, 2019

--

You’re going to read about login brute-force protection practices and examples written on Node.js. The same patterns can be applied to any web application.

It consists of two parts:

  1. The first part is about common analysis, practices, pros and cons.
  2. This part consists of Node.js examples with rate-limiter-flexible package. It implements fixed window algorithm for limiting actions by key and works with Redis, Memcached, MongoDB, MySQL, PostgreSQL which is good for distributed applications too.

You can go to exact example by next links:

  1. Block source of requests by IP
  2. Block source of requests by IP, Username and IP
  3. Block source of requests by IP, Username and IP, Username globally

Note, if there is a Reverse Proxy like Nginx in your application’s infrastructure, you should configure brute-force protection and rate limiting there. If there is some load balancer with similar options, try it. There are also 3rd party authorisation providers, they usually implement best security practices.

Otherwise, implement one of examples below. There are 4 approaches different in cost and strength described in a section What is enough for my application? points from the first part.

Number of allowed failed attempts should be chosen depending on requirements and nature of an application.

Block source of requests by IP

The most simple example would be limiting number or slowing response of failed login attempts by IP within short period of time. It usually doesn’t help against slow brute force, when attack lasts for months.

Note, it is better to configure the logic from this example on reverse-proxy or with tools like Fail2ban, if that is possible.

This example referrers to the first option from the previous part. It should be protected against slow and fast brute-force attacks separately. Create 2 types of limiters. The first blocks IP for 10 minutes on 5 failed attempts per last 30 seconds. The second blocks IP for 1 day on 100 failed attempts per day.

Maximum number of tried passwords is 3000 per month. Which is good enough. However, blocked IP may be many real devices over Proxy, as a result innocent users may be blocked.

Block source of requests by IP, Username and IP

This example referrers to the second option from the previous part

Create 2 types of limiters. The first counts number of consecutive failed attempts and allows maximum 10 by username and IP pair. The second blocks IP for 1 day on 100 failed attempts per day.

It requires some unblock function, which should be triggered, when user proves his identity any suitable way. delete method by username and IP should be used for that.

This option is more user friendly, as it doesn’t block IP on fast brute-force attack. Still innocent users with the same IP as a hacker may be blocked.

Block source of requests by IP, Username and IP, Username globally

This example referrers to the third option from the previous part

Create 3 limiters. The first counts number of consecutive failed attempts and allows maximum 10 by username and IP pair. The second blocks IP for 1 day on 100 failed attempts per day. And the third blocks username on 50 failed attempts per day.

Trusted devices are not blocked by IP or Username, but still blocked by Username+IP pair on consecutive attempts.

Block source of requests considering geolocation

The forth example from the first part describes some options how to use geolocation to minimise risks. You should analyse what kind of metrics would be helpful to detect anomalies. It completely depends on web application nature and requirements.

Conclusion

Choose how strong protection should be depending on application.

The second example is good enough for startups, forums and small projects, which probably not a target for attacks.

The third example isn’t too complex and at the same time provides good user experience in case if there is a way to prove device is trusted.

--

--