我想知道是否可以使用简单的 IP 表规则来防止小型 (D)DoS 攻击?
我说的“少量”是指它们用来自一个或两个 IP 地址的大约 400 多个请求淹没了我的 Web 服务器。当我注意到它们开始攻击我的 Web 服务器后,我可以删除这些 IP 地址,但 IP 表通常需要几分钟才能针对该 IP 启动,然后开始完全删除它,这样它就不会影响该 Web 服务器。
我使用以下命令删除 IP:
iptables -I INPUT -s "IP HERE" -j DROP
然后显然保存它:
/etc/init.d/iptables save
我通常使用以下命令找出攻击 IP 地址:
netstat -plan|grep :80|awk '{print $5}'|cut -d: -f 1|sort|uniq -c|sort -n
这样做的问题是我必须在场,而且这需要我在事后采取行动。是否有 IP 表规则,我可以在 IP 地址达到 150 个连接后立即使用它来删除它?这样我就不必担心它会压垮 Web 服务器,而且我也不必当时在场来阻止它。
顺便说一句,如果有必要的话我在 CentOS 上使用 Apache。
感谢您的时间。
答案1
对于提供灵活性的东西,请查看最近(和限制)模块。最近将跟踪 IP 在给定时间范围内建立的连接数,并可用于触发特定规则。最近模块(相对)占用大量 CPU - 但与加载动态页面相比,这是可以接受的。
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p tcp -m multiport --dports 80,443 -m recent --update --seconds 3600 --name BANNED --rsource -j DROP
-A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -j ATTK_CHECK
-A ATTACKED -m limit --limit 5/min -j LOG --log-prefix "IPTABLES (Rule ATTACKED): " --log-level 7
-A ATTACKED -m recent --set --name BANNED --rsource -j DROP
-A ATTK_CHECK -m recent --set --name ATTK –-rsource
-A ATTK_CHECK -m recent --update --seconds 600 --hitcount 150 --name ATTK --rsource -j ATTACKED
-A ATTK_CHECK -m recent --update --seconds 60 --hitcount 50 --name ATTK --rsource -j ATTACKED
-A ATTK_CHECK -j ACCEPT
从本质上来说,上述内容相当于:
- 接受已经建立的连接(即它们已经通过了我们的规则)
- 删除被禁止 IP 在端口 80 和 443(SSL)上的所有连接 - 如果它们继续尝试连接,请延长时间 - 等待一小时(不进行任何连接尝试)后再解除对它们的阻止。
- 根据我们的规则检查新连接:
- 考虑 10 分钟内超过 150 个连接的攻击
- 考虑 1 分钟内超过 50 个连接进行攻击
- 记录攻击(但每分钟不要超过 5 条 - 不想淹没我们的日志);并阻止连接
有关更详细的解释以及我使用的上述分层版本,请参阅本文
请记住,ipTables 根本无法缓解网络拥塞,并且对任何分布式攻击都无效 - 它的优势在于安全性和减轻服务器的负载。
答案2
你能使用 iptables 来阻止这样的滥用者,但你必须小心,因为 iptables 非常耗费 CPU。每个数据包都会根据每条规则进行检查,因此添加规则很快就会导致服务器耗尽周期。我曾经有一个客户,每次他们想阻止某人时都会添加一条新规则,然后有一天他们的流量略高于正常水平,系统崩溃了。表格可以减少查看的规则数量,但你不能在 iptables 中随意添加大量规则。
另一种选择是黑洞路由:
ip route add blackhole $IP_HERE
ip route flush cache
路由表经过哈希处理(使用哈希表),而 iptables 规则必须按顺序查看,效率要低得多。这样,您可以毫无问题地拥有数十万条路由,而对于每个请求,运行数千条 iptables 规则将变得很成问题。
至于你的第二个问题,你可以使用该hashlimit
模块为滥用者创建自动黑名单。请参阅我的帖子关于防止 DDoS 攻击了解更多详细信息,但简短形式为:
iptables -A INPUT -p tcp --dport 80 -m hashlimit --hashlimit-upto 50/min \
--hashlimit-burst 500 --hashlimit-mode srcip --hashlimit-name http -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP