Limit TCP requests to each IP address

I am wondering how to limit TCP requests to one client (per specific IP) in Java. For example, I would like to allow a maximum of X requests in Y seconds for each client IP address. I was thinking about using a static timer / TimerTask in combination with a HashSet of temporary restricted IP addresses.

private static final Set<InetAddress> restrictedIPs = Collections.synchronizedSet(new HashSet<InetAddress>()); private static final Timer restrictTimer = new Timer(); 

Therefore, when a user connects to the server, I add his IP address to the list of restrictions and run the task to restrict it for X seconds.

 restrictedIPs.add(socket.getInetAddress()); restrictTimer.schedule(new TimerTask() { public void run() { restrictedIPs.remove(socket.getInetAddress()); } }, MIN_REQUEST_INTERVAL); 

My problem is that during the execution of the task, the socket object may be closed and the remote IP address will no longer be available ...

Any ideas are welcome! Also, if someone knows the Java-framework-built-in way to achieve this, I would really love to hear it.

+4
source share
2 answers

A simple solution for this would be:

 final InetAddress ip = socket.getInetAddress(); restrictedIPs.add(ip); restrictTimer.schedule(new TimerTask() { public void run() { restrictedIPs.remove(ip); } }, MIN_REQUEST_INTERVAL); 

The problem with this method is that additional streams are required to remove restricted IP addresses. It might be easier to save the InetAddress card in a time stamp to track the last time they accessed the page. That way, you can simply check this timestamp every time a client starts a request.

+1
source

One option is to use netfilter to accomplish this. Not β€œpure” java, but probably the solution that will be the most reliable and error-free. This example is taken from debian-administration

 iptables -I INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent \ --set iptables -I INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent \ --update --seconds 60 --hitcount 4 -j DROP 

EDIT:

To quickly fix your code, save the IP address and add an account before blocking, i.e. (pseudo):

 IPaddress addr = socket.getAddress(); int hitcount = hitcountMap.get(addr).value(); if (hitcount <= HIT_MAX) { //only increase if person hasn't reached roof, prevents 'overblocking' hitcountMap.get(addr).increase(); unblockTimer.schedule(hitcountMap.get(addr).decrease(), BLOCK_TIMEOUT); } if (hitcount > HIT_MAX) { connection.drop(); } 

This should make the block last with the maximum BLOCK_TIMEOUT (no errors are guaranteed). You should consider using a semaphore for counting, since you are likely to run this code from many streams, depending on your streaming model, of course.

+3
source

Source: https://habr.com/ru/post/1311595/


All Articles