2

Having a server that has to handle lots of TCP-requests from gprs-modules I think it is handy to set up something to protect this server from multiple requests from certain ip's.

Now I want to make something(within python) that will check how much times a certain ip tries to connect and if this exceeds a given amount of tries this ip will be blocked for a given amount of time (or forever).

I am wondering if there are libraries present to do this, or how I should tackle this problem in my code.

4

4 回答 4

7

不要从你的代码中解决这个问题——这就是防火墙的设计目的。

使用 iptables 很简单:

iptables -I INPUT -p tcp --dport $PORT -i eth0 -m state --state NEW -m recent --set

iptables -I INPUT -p tcp --dport $PORT -i eth0 -m state --state NEW -m recent --update --seconds 600 --hitcount 2 -j DROP

上面的意思是“丢弃任何在 10 分钟内在端口 $PORT 进行超过 2 次连接尝试的东西”

于 2013-06-03T11:52:21.870 回答
2

正如布尔汗·哈立德所说。你不想在你的代码中尝试这个。它的性能不是很好,这就是防火墙的用途。

iptables -I INPUT -p tcp --dport $PORT -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport $PORT -i eth0 -m state --state NEW -m recent --update --seconds 600 --hitcount 2 -j DROP

这个例子非常有用,但不是很方便。问题是您还限制了良好/受信任的连接。

你需要更加灵活。在基于 linux 的操作系统上,您可以使用 fail2ban。这是一个非常方便的工具,可以通过使用动态 iptables 规则来防止您的服务遭受暴力攻击。在 Debian/Ubuntu 上,您可以使用 apt-get 安装它。如果您使用的是 CentOS,则需要使用第三方存储库。

  1. 将每个连接记录到日志文件中:

    [Jun 3 03:52:23] server [pid]: Connect from 1.2.3.4
    [Jun 3 03:52:23] server [pid]: Failed password for $USER from 1.2.3.4 port $DST
    [Jun 3 03:52:23] server [pid]: Connect from 2.3.4.5
    [Jun 3 03:52:23] server [pid]: Successful login from 2.3.4.5
    
  2. 现在用 fail2ban 监控这个文件并定义一个正则表达式来区分成功和失败的登录。告诉fail2ban它应该为您阻止IP多长时间以及您是否想收到电子邮件通知。

该文档非常好,因此请在这里查看如何配置 fail2ban 来监控您的日志:fail2ban docu

您不必只关注失败的登录。您也可以尝试注意端口扫描。最大的胜利:不仅保护您的应用程序。还可以保护您的 SSH、HTTP 等登录,以免被暴力破解!;)

于 2013-06-03T12:32:38.627 回答
2

如果您决定确实要在代码中处理此问题,则不需要单独的库(尽管使用一个可能会更有效),您可以将以下内容添加到您的连接处理程序中:

from collections import defaultdict, deque
from datetime import datetime

floodlog = defaultdict(deque)


def checkForFlood(clientIP):
    """check if how many times clientIP has connected within TIMELIMIT, and block if more than MAX_CONNECTEIONS_PER_TIMELIMIT"""

    now = datetime.now()
    clientFloodLog = floodlog[clientIP]
    clientFloodLog.append(now)
    if len(clientFloodLog) > MAX_CONNECTIONS_PER_TIMELIMIT:
        earliestLoggedConenction = clientFloodLog.popleft()
        if now - earliestLoggedConnection < TIMELIMIT:
            blockIP(clientIP)
于 2013-06-03T11:57:37.277 回答
1

对于纯 Python 解决方案,我认为您可以重用我为同一问题开发的东西,但从客户端的角度来看:避免向服务提供商发出超过“每秒 x 次尝试”的问题。

该代码可在GitHub上找到:您可能可以重复使用其中的大部分内容,但您需要替换time.sleep“黑名单”机制的调用。

于 2013-06-03T11:52:08.370 回答