限制每个IP的TCP请求

时间:2010-06-02 07:53:23

标签: java tcp request limit

我想知道如何在Java中限制每个客户端(每个特定IP)的TCP请求。例如,我想为每个客户端IP允许每Y秒最多X个请求。我想过将静态Timer / TimerTask与临时受限IP的HashSet结合使用。

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

private static final Timer restrictTimer = new Timer();

因此,当用户连接到服务器时,我将他的IP添加到受限列表中,并启动任务以在X秒内取消限制。

restrictedIPs.add(socket.getInetAddress());

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

},  MIN_REQUEST_INTERVAL);

我的问题是,在任务运行时,套接字对象可能会关闭,远程IP地址将无法访问...

欢迎任何想法!此外,如果有人知道Java框架内置的方法来实现这一点,我真的很想听听它。

2 个答案:

答案 0 :(得分:3)

一种选择是使用netfilter来实现这一目标。不是'纯'java,但可能是最强大和无错误的解决方案。此示例取自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

编辑:

只需快速修复代码,保存IP地址并在阻止之前添加计数,即(伪):

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();
}

这应该使块最后保持最大BLOCK_TIMEOUT(不保证无bug)。您应该考虑使用信号量进行计数,因为您(可能)会从许多线程运行此代码,具体取决于您的线程模型。

答案 1 :(得分:1)

一个简单的解决方案是:

final InetAddress ip = socket.getInetAddress();
restrictedIPs.add(ip);

restrictTimer.schedule(new TimerTask()
{
  public void run()
  {
    restrictedIPs.remove(ip);
  }

},  MIN_REQUEST_INTERVAL);

此方法的问题是需要额外的线程才能删除受限制的IP地址。也许将InetAddress的Map保存到时间戳更容易,以便跟踪他们上次访问页面的时间。这样,您可以在每次客户端启动请求时检查此时间戳。