写一个 shell 脚本,创建脚本文件 /usr/local/bin/check_conn.sh
#!/bin/bash
if [[ $EUID -ne 0 ]]; thenecho "This script must be run as root." >&2exit 1
fi
# 连接数阈值
THRESHOLD=50# 白名单 IP(空格分隔)
WHITELIST_IPS="0.0.0.0 127.0.0.1"# 日志文件
ABUSE_LOG="/var/log/conn_abuse.log"# 封禁时间(秒)
BAN_TIME=86400# 获取当前时间戳
NOW=$(date +%s)echo "[$(date '+%Y-%m-%d %H:%M:%S')] iptables 定时任务执行" >> "$ABUSE_LOG"# 统计连接数
netstat -ant | awk '{print $5}' | cut -d: -f1 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | \sort | uniq -c | sort -nr | while read count ip; doecho "$ip $count"# 过滤非法行或白名单 IP[[ ! "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] && continuefor white_ip in $WHITELIST_IPS; do[[ "$ip" == "$white_ip" ]] && continue 2done# 判断是否超过阈值if [[ "$count" -gt "$THRESHOLD" ]]; then# 检查是否已被封禁sudo iptables -L -n --line-numbers | grep "$ip"| grep DROP 2>/dev/nullif [[ $? -ne 0 ]]; thenecho "[$(date '+%Y-%m-%d %H:%M:%S')] Blocking $ip with $count connections" >> "$ABUSE_LOG"echo "----$ip--------$count"# 添加 iptables 封禁sudo iptables -I INPUT -s "$ip" -j DROP && echo "[debug]INPUT drop success for $ip" >> "$ABUSE_LOG"sudo iptables -I FORWARD -s "$ip" -j DROP && echo "[debug]FORWARD drop success for $ip" >> "$ABUSE_LOG"sudo iptables -I OUTPUT -d "$ip" -j DROP && echo "[debug]OUTPUT drop success for $ip" >> "$ABUSE_LOG"# 强制断开现有连接(使用 conntrack 工具)if command -v conntrack &>/dev/null; thenconntrack -D -s "$ip" && echo "[debug]conntrack -D -s $ip" >> "$ABUSE_LOG"conntrack -D -d "$ip" && echo "[debug]conntrack -D -d $ip" >> "$ABUSE_LOG"fi# 设置定时任务自动解封echo "sudo iptables -D INPUT -s $ip -j DROP; sudo iptables -D FORWARD -s $ip -j DROP; sudo iptables -D OUTPUT -d $ip -j DROP" | \at NOW + $((BAN_TIME / 60)) minutes 2>/dev/nullfifi
done
配合 cron
定时执行这个脚本:
*/2 * * * * /usr/local/bin/check_conn.sh
脚本功能介绍
-
定义变量:设置连接数阈值(200)、白名单IP、日志路径和封禁时间(24小时)。
-
统计连接数:使用
netstat
获取所有TCP连接,提取远程IP并统计连接数。 -
过滤白名单和本地IP:跳过白名单中的IP,并检查IP格式的有效性。
-
封禁处理:若IP连接数超过阈值且未被封禁,则通过
iptables
封禁,并记录日志。 -
断开现有连接:使用
conntrack
强制终止现有连接(如果可用)。 -
自动解封:使用
at
命令在封禁时间后移除iptables
规则。