一些 IP 正在打开我服务器的数千个连接。我有一台 Ubuntu 14 服务器。我使用以下命令检查总连接数:
netstat -an | grep tcp | awk'{print $5}'| cut -f 1 -d : | sort | uniq -c | sort -n
然后我使用以下 iptables 规则来阻止罪魁祸首 IP。
iptables -I 输入 1 -s xxxx -j DROP
它运行正常,并阻止了 IP 地址。但是,我无法全天候在线监控服务器。我想知道是否有任何 Shell 脚本可以用来自动执行此操作?例如,如果某个 IP 在任何时候打开的连接数超过 X 个,则应该会自动被上述 iptables 规则禁止。
答案1
首先,不要重新发明轮子。这正是denyhosts
:
DenyHosts is a python program that automatically blocks ssh attacks by
adding entries to /etc/hosts.deny. DenyHosts will also inform Linux
administrators about offending hosts, attacked users and suspicious
logins.
据我所知,denyhosts
仅用于ssh
连接,但也有
fail2ban
处理几乎所有事情的:
Fail2Ban consists of a client, server and configuration files to limit
brute force authentication attempts.
The server program fail2ban-server is responsible for monitoring log
files and issuing ban/unban commands. It gets configured through a
simple protocol by fail2ban-client, which can also read configuration
files and issue corresponding configuration commands to the server.
两者均可在存储库中找到:
sudo apt-get install denyhosts fail2ban
如果你愿意,你也可以编写脚本。例如:
#!/usr/bin/env sh
netstat -an |
awk -vmax=100 '/tcp/{split($5,a,":"); if(a[1] > 0 && a[1]!="0.0.0.0"){c[a[1]]++}}
END{for(ip in c){if(c[ip]>max){print ip}}}' |
while read ip; do iptables -I INPUT 1 -s "$ip" -j DROP; done
将awk
提取 IP 并对其进行计数,仅打印那些出现max
次数超过 的 IP(此处为 ,-vmax=100
请进行相应更改)。然后将 IP 输入到运行相关iptables
规则的 while 循环中。
为了全天候运行该命令,我会创建一个 cronjob,每隔一分钟左右运行一次上述命令。将此行添加到/etc/crontab
* * * * * root /path/to/script.sh
答案2
一个可能的替代方案是使用模块识别并处理 iptables 规则集中的所有问题 IP 地址recent
。这种方法的挑战在于默认命中数限制为 20,因此需要偏离默认值或创建更高级别的进位计数器以实现更高的命中数触发点。
以下示例来自我的 iptables 规则集,如果某个 IP 地址在 12 分钟内通过端口 80 建立 80 个新 TCP 连接,则该 IP 地址将被禁止超过 1 天。一旦被列入坏人名单,任何连接尝试都会将 1 天计数器重置为 0。此方法最多可以达到 400 次命中,然后才需要扩展到另一个进位(我已经测试了另一个进位链)。请注意,发布的代码具有基础结构,仅用于在多个较短时间触发器上长时间禁止。目前,我已将其设置为仅在第一次触发时长时间禁止。
#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in4
#
# A NEW Connection on port 80 part 4.
#
# multiple hits on the banned list means you get a one day ban.
# (I re-load the firewall rule set often, so going longer makes
# little sense.)
#
# Custom tables must exist before being referenced, hence the order
# of these sub-toutines.
#
# Place holder routine, but tested. Logs if a day ban would have
# been activated.
#
$IPTABLES -N http-new-in4
#$IPTABLES -A http-new-in4 -m recent --set --name HTTP_BAN_DAY
$IPTABLES -A http-new-in4 -j LOG --log-prefix "DAY80:" --log-level info
$IPTABLES -A http-new-in4 -j DROP
#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in3
#
# A NEW Connection on port 80 part 3.
#
# carry forward to the actual banned list:
# Increment this count. Leave the previous count.
#
# Custom tables must exist before being referenced, hence the order
# of these sub-toutines.
#
$IPTABLES -N http-new-in3
$IPTABLES -A http-new-in3 -m recent --remove --name HTTP_02
$IPTABLES -A http-new-in3 -m recent --update --hitcount 1 --seconds 86400 --name HTTP_BAN -j http-new-in4
$IPTABLES -A http-new-in3 -m recent --set --name HTTP_BAN
$IPTABLES -A http-new-in3 -j LOG --log-prefix "BAN80:" --log-level info
$IPTABLES -A http-new-in3 -j DROP
#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in2
#
# A NEW Connection on port 80 part 2.
#
# carry forward from previous max new connections per unit time:
# Increment this count and clear the lesser significant count.
#
$IPTABLES -N http-new-in2
$IPTABLES -A http-new-in2 -m recent --remove --name HTTP_01
$IPTABLES -A http-new-in2 -m recent --update --hitcount 3 --seconds 720 --name HTTP_02 -j http-new-in3
$IPTABLES -A http-new-in2 -m recent --set --name HTTP_02
$IPTABLES -A http-new-in2 -j LOG --log-prefix "CARRY80:" --log-level info
$IPTABLES -A http-new-in2 -j ACCEPT
#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in
#
# A NEW Connection on port 80:
#
$IPTABLES -N http-new-in
echo Allowing EXTERNAL access to the WWW server
# . check the static blacklist.
#
# http related
$IPTABLES -A http-new-in -i $EXTIF -s 5.248.83.0/24 -j DROP
... delete a bunch on entries ...
$IPTABLES -A http-new-in -i $EXTIF -s 195.211.152.0/22 -j DROP
$IPTABLES -A http-new-in -i $EXTIF -s 198.27.126.38 -j DROP
# . check the dynamic banned list
#
# The 1 Hour banned list (bumped to more than a day):
$IPTABLES -A http-new-in -m recent --update --seconds 90000 --name HTTP_BAN --rsource -j LOG --log-prefix "LIM80:" --log-level info
$IPTABLES -A http-new-in -m recent --update --seconds 90000 --name HTTP_BAN --rsource -j DROP
# A generic log entry. Usually only during degugging
#
#$IPTABLES -A http-new-in -j LOG --log-prefix "NEW80ALL:" --log-level info
# Dynamic Badguy List. Least significant hit counter. Detect and DROP Bad IPs that do excessive connections to port 80.
#
$IPTABLES -A http-new-in -m recent --update --hitcount 20 --seconds 240 --name HTTP_01 -j http-new-in2
$IPTABLES -A http-new-in -m recent --set --name HTTP_01
$IPTABLES -A http-new-in -j LOG --log-prefix "NEW80:" --log-level info
$IPTABLES -A http-new-in -j ACCEPT
... a bunch of stuff not included here
# Allow any related traffic coming back to the server in.
#
#
$IPTABLES -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -m state --state ESTABLISHED,RELATED -j ACCEPT
... the above is needed before the below ...
# If required, go to NEW HTTP connection sub-routine
#
$IPTABLES -A INPUT -i $EXTIF -m state --state NEW -p tcp -s $UNIVERSE -d $EXTIP --dport 80 -j http-new-in