Alex
Alex

Reputation: 68406

How to correctly block IP adresses in Node.JS server app?

Say I have a Node.JS server app and I want to block users that failed to log in 3 consecutive times, what is the correctly way to do that?

Should I handle the blocking part in the server app, basically after the user has connected but has not yet logged in, or is there some lower level stage where I am supposed to do it, so it doesn't even reach my Node.JS app?

Upvotes: 16

Views: 21980

Answers (9)

Viral Patel
Viral Patel

Reputation: 1156

First thing that can come to mind after detecting an attack is to block an attacker’s IP address.

IP blocking is not the right way to prevent users after the number of incorrect logins.

But that’s not a very good way of deterring an attack, because:

  • The attacker can easily overcome this by dynamically changing the IP address
  • Blocking a public IP may cut off other users that use it

There are several different techniques for security to stop this types of attacks,

  1. You can manage logs of failed logins for a user account and calculate how many failed attempts are done from the same IP within the last N minutes based on that you can temporarily Deactivate the account of the user.

  2. After failing to log in the account, you can start showing captcha when the user tries to login after 3 failed or add security questions.

  3. Send email to the user regarding failed attempts and the method to recover the account by changing the password.

Upvotes: 1

Bharata
Bharata

Reputation: 14155

Before you do it

You should think about what should happens if:

  1. Two colleagues work in the same office and have same IP adress. The bad colleague wants log in from different PC to the account of his colleague and made 3 consecutive times failed logins. Now the account owner wants log in and what will you do in this case?
  2. Father and his son are at home, have same IP adress and the son wants log in from different PC to the account of his father and made 3 consecutive times failed logins. Now the father wants log in and what will you do in this case?

And some users have static IP address (they can not change it).

Solution

Because of this I would block the account and IP address(es), and then I would send an email to the account owner with a link wich will deblock the account and this without the require of the password changing. The account owner should also answer about deblocking of IP address(es), because he knows his IP address(es).

How to do it (block an IP address)

The preferable solution would be to block an IP address at a lower level – before it gets to Node.JS because all networking happens in the operating system kernel and the kernel can block it more efficiently and sooner in the connection than Node.JS could do it.

But at first to answer your question...

How to block it with Node.JS

var blackList =
[
    '77.88.99.1',
    '88.77.99.1'
];

var http = require('http');
var server = http.createServer(function(req, res)
{
    var ip = req.ip 
            || req.connection.remoteAddress 
            || req.socket.remoteAddress 
            || req.connection.socket.remoteAddress;

    if(blackList.indexOf(ip) > -1)
    {
        res.end(); // exit if it is a black listed ip
    }

}).listen(80, '127.0.0.1');

And Node.js http.Server has a connection event. You could do it also on this way:

server.on('connection', function(socket)
{
    // console.log(socket.remoteAddress);
    // Put your logic here
});

How to block it with Linux (for example)

Sometime it is necessary to block incoming connection or traffic from specific remote host. iptables is administration tool for IPv4 packet filtering and NAT under Linux kernel. Following tip will help you to block attacker or spammers IP address.

How do I block specific incoming ip address?

Following iptable rule will drop incoming connection from host/IP 202.54.20.22:

iptables -A INPUT -s 202.54.20.22 -j DROP
iptables -A OUTPUT -d 202.54.20.22 -j DROP

A simple shell script to block lots of IP address

If you have lots of IP address use the following shell script:

A) Create a text file:

# vi /root/ip.blocked

Now append IP address:

# Ip address block  file
202.54.20.22
202.54.20.1/24
#65.66.36.87

B) Create a script as follows or add following script line to existing iptables shell script:

BLOCKDB="/root/ip.blocked"
IPS=$(grep -Ev "^#" $BLOCKDB)
for i in $IPS
do
iptables -A INPUT -s $i -j DROP
iptables -A OUTPUT -d $i -j DROP
done

C) Save and close the file.


© Source Linux Iptables block incoming access to selected or specific ip address

Upvotes: 14

Manish
Manish

Reputation: 952

Blocking the IP address after the user failed to log in 3 consecutive times is not a good idea. Because

  1. An IP address can be changed.
  2. The original owner of the account in your app and the person who is trying to guess the password may be on the same network and hence, same IP address.

So what you can do to increase the security of your application without blocking the IP address? The solution is

  1. After failing to log in the account, you can start showing reCaptcha while the user tries to login after 3 failed attempts.

  2. You can temporarily Deactivate the account of the user in your app if the username (or email that specifically points to any account in your application database) and send the email regarding changing the password to recover back the account or something else according to your application.

There is one more idea to block the IP address if you really want to blog the IP address after 3 failed attempts you can do these steps:

  1. Temporarily block the IP address of the user. After that,
  2. Send email to the account owner regarding failed attempts and the method to recover the account by changing the password.
  3. Start showing reCaptcha for that particular IP address or account to login after 3 failed attempts so that if IP address also gets changed It will make it a little bit more difficult to do hit and trial.

Upvotes: 1

Pouya Darabi
Pouya Darabi

Reputation: 2315

Why do you want to block a user?

As a Security Researcher, I will give you a general answer that is not specificity for NodeJS.

IP blocking is almost ineffective because it can be easily changed.

If you block the user the attacker can easily disrupt part of the usability of your site by brute-forcing on other users or specific users to disable their accounts.

I personally use a challenge system to cover both conditions

  • Count the number of failed login attempts for IP
  • Count the number of failed login for users

Finally, before doing the login request, first check the user's IP, in your blacklist (10 times should be enough). If the IP was allowed then check requested user failed logins (5 times should be good) and if one of these checks fails just send a challenge back and stop login action.

You can use a secure captcha or anything else. If the client solves it correctly, do login action for it. and make sure you reset incorrect login count for users. But for IP don't do it instantly and reset it daily, weekly, or monthly.

So, any IP after 10 times of incorrect login should face with challenge and at user level after 5 incorrect logins with any IP address must pass the challenge

This way, you won't make any issues for normal users and also preventing the attacker to brute-force.

Upvotes: 14

x00
x00

Reputation: 13823

In your case

to block users that failed to log in

The correct way is not to do that at all.

IP blocking is more about DoS protection, or legal requirements.

  1. A user can login from different IPs.
  2. Different users can login from the same IP.

So if you block by IP

  1. A malicious user will simply change it.
  2. A fair user will be blocked for no reason and you can loose... depending on your case... nothing or quite a lot.

(Also why to block an IP but not an account?)

But if you wanna do it anyway, then I guess that your're asking not about "how?" exactly you should do it, but "where?"

Should I handle the blocking part in the server app, basically after the user has connected but has not yet logged in, or is there some lower level stage where I am supposed to do it, so it doesn't even reach my nodejs app?

Well, that depends.

  1. It's easier to do inside your node.js server's code (with or without some third-party npm modules), if this code is the only thing you have, and your server is not supposed to handle tons of requests.
  2. But if you server is under a heavy load, or you do find yourself under DoS-attacks from time to time. Then, yes, it's better go low level, and to add Nginx (or similar) to your infrastructure. blacklisting-ip-addresses

    so it doesn't even reach my nodejs app

  3. If you have Nginx already, then there're more reasons to use it, and not to waist your's and your server performance on technicalities, but focus on the business logic. That will require some effort too (see the link above) but it'd be more robust solution.

Upvotes: 1

Shaheer Khan
Shaheer Khan

Reputation: 74

You can get IP of the client

const remoteAddresParams = req._remoteAddress.split(':');
const IP = remoteAddresParams[remoteAddresParams.length -1];

then you can create a your own middleware , the code below may be incorrect but you get the idea.

e-g

app.use((req, res, next) => {
    const blockedIPs = ['1.1.1.1', '0.0.0.0'];
    const remoteAddresParams = req._remoteAddress.split(':');
    const clientIP = remoteAddresParams[remoteAddresParams.length -1];
    isClientBlocked= blockedIPs.any(ip => ip.toString() === clientIP.toString());
    res.status(403)
    res.json({success: 0, message: 'you are blocked for some reason'})
});

`

Upvotes: 1

Tymur Taraunekh
Tymur Taraunekh

Reputation: 229

If you are using Express in your app, then you can use express-ipfilter or similar package in order to block access by ip.

Simple example will look like this:

// Init dependencies
const express = require('express')
const ipfilter = require('express-ipfilter').IpFilter
 
// Blacklist the following IPs
const ips = ['127.0.0.1']
 
// Create the server
app.use(ipfilter(ips))
app.listen(3000)

You can store the list of ips in memory or some kind of storage like Redis, and add ips dynamically (ex. when user failed to log in 3 consecutive times). You might also want to block ips only for certain period of time (ex. one hour).

Upvotes: 1

Daniele Ricci
Daniele Ricci

Reputation: 15797

It seems this logic should be implemented by the same component responsible for the login; otherwise some communication between the two components would be required.

If the login check is performed in the Node.js server app, it is the right place to perform the new check as well.

Upvotes: 1

billi
billi

Reputation: 564

I think it user should see blocked message when they again try to login.

As other user from same IP address with correct credentials must be able to login into the system.

Upvotes: 1

Related Questions