iptables封堵实验
一、脚本功能分析
1. 变量定义区
logfile=/usr/local/nginx/logs # Nginx日志目录(需确保存在access.log)
last_minutes=1 # 检测时间窗口:1分钟内的访问
- 作用:定义日志路径和检测周期,后续步骤依赖这两个变量。
2. 时间范围计算
start_time=`date -d"$last_minutes minutes ago" +"%d/%m/%Y:%H:%M:%S"` # 开始时间(1分钟前)
stop_time=`date +"%d/%m/%Y:%H:%M:%S"` # 结束时间(当前时间)
- 潜在 BUG:
Nginx 默认日志的时间格式是日/月缩写/年:时间
(如07/Aug/2025:10:00:00
),但脚本生成的时间格式是日/数字月/年
(如07/08/2025:10:00:00
),两者格式不匹配,导致awk
无法正确筛选时间范围!
3. 日志统计核心逻辑
tac $logfile/access.log | awk -v st="$start_time" -v et="$stop_time" '{t=substr($4,2); # 提取日志时间字段(去掉开头的`[`,如日志中时间是`[07/Aug/2025:10:00:00 +0800]`,提取后为`07/Aug/2025:10:00:00 +0800`)if(t>=st && t<=et){print $1} # 筛选时间范围内的记录,输出客户端IP($1是Nginx日志的第一列,即客户端IP)
}' | sort | uniq -c | sort -nr > $logfile/log_ip_top10
去掉开头的“【”
log_ip_top10
的作用:- 是临时统计文件,存储
1分钟内
每个 IP 的访问次数,按 “次数从高到低” 排序。 - 内容格式:
[次数] [IP]
(如200 192.168.1.100
表示该 IP 1 分钟内访问了 200 次)。
- 是临时统计文件,存储
4. 恶意 IP 提取与封禁(未完成)
ip=`cat $logfile/log_ip_top10 | awk '{if($1 > 100)print $2}'` # 提取“次数>100”的IP
for line in $ip
doecho $line >> $logfile/getip.txt # 记录到getip.txtecho $lineiptables # 此处命令不完整!需补充封禁规则(如封禁80/443端口)
done
- 问题:
iptables
命令未写完整,实际需补充如iptables -I INPUT -p tcp --dport 80,443 -s $line -j DROP
。
二、log_ip_top10
详细解释
属性 | 说明 |
---|---|
是什么 | 临时文本文件,存储 “时间窗口内各 IP 的访问次数”,按次数降序排列。 |
路径 | 由 logfile 决定,即 $logfile/log_ip_top10 (如 /usr/local/nginx/logs/log_ip_top10 )。 |
内容格式 | 每行格式:[访问次数] [IP] (如 150 1.2.3.4 表示 1.2.3.4 访问了 150 次)。 |
作用 | 作为中间结果,供后续步骤筛选 “超过阈值的恶意 IP”。 |
如何生成 | 通过 tac (反向读日志)→ awk (筛时间)→ sort+uniq (统计次数)→ sort -nr (降序)生成。 |
三、替换 / 修改时的核心注意事项
1. 修复时间格式不匹配的 BUG
Nginx 日志时间是 日/月缩写/年
(如 07/Aug/2025
),但脚本生成的是 日/数字月/年
(如 07/08/2025
),导致时间筛选失效。
解决方案:修改 date
命令的格式为 %b
(英文月份缩写):
start_time=`date -d"$last_minutes minutes ago" +"%d/%b/%Y:%H:%M:%S"` # 如 07/Aug/2025:10:00:00
stop_time=`date +"%d/%b/%Y:%H:%M:%S"` # 匹配Nginx日志格式
2. 调整日志路径(看是编译的还是apt安装的,我这里是直接编译安装的)
若 Nginx 日志不在 /usr/local/nginx/logs
,修改 logfile
变量:
logfile=/var/log/nginx # 示例:Ubuntu默认Nginx日志路径
3. 阈值与时间窗口调整
- 时间窗口:
last_minutes=1
表示 1 分钟,可改为5
(5 分钟)、10
等。 - 访问阈值:当前
awk
中$1 > 100
表示 “次数> 100 次”,可改为变量(更易维护):threshold=150 # 自定义阈值 ip=`cat $logfile/log_ip_top10 | awk -v threshold=$threshold '{if($1 > threshold)print $2}'`
4. 完善 iptables 封禁规则
补充完整的封禁命令(以封禁 80、443 端口为例):
iptables -I INPUT -p tcp -m multiport --dport 80,443 -s $line -j DROP
- 进阶优化:添加 “防重复封禁” 逻辑(检查 IP 是否已在规则中,或维护黑名单文件)。
5. 错误处理增强
- 检查日志文件是否存在:
if [ ! -f "$logfile/access.log" ]; thenecho "错误:日志文件 $logfile/access.log 不存在!"exit 1 fi
- 处理空统计文件(避免循环报错):
ip=`cat $logfile/log_ip_top10 | awk '{if($1 > 100)print $2}'` if [ -z "$ip" ]; then # 如果ip为空,跳过循环echo "未发现超过阈值的IP"exit 0 fi
四、完整修正后的示例(判断统计文件是否存在,并且写上计划任务,每天0时开启,并且每5分钟执行一次)
#!/bin/bash
# 防止扫描器攻击:检测Nginx日志,自动封禁高频访问IP
# 功能:自动创建统计文件、防重复封禁、支持计划任务定时执行# ======================== 配置区(按需修改) ========================
logfile=/usr/local/nginx/logs # Nginx日志目录(确保存在)
last_minutes=1 # 检测时间窗口(分钟)
threshold=100 # 访问次数阈值(超过此值将被封禁)
block_ports="80,443" # 封禁的端口(Web服务端口)
stat_file="$logfile/log_ip_top10" # IP访问统计文件(核心文件)
blacklist="$logfile/blacklist.txt" # 已封禁IP记录(防重复封禁)
# ==================================================================# 关键优化:自动创建统计文件(如果不存在)
if [ ! -f "$stat_file" ]; thentouch "$stat_file" # 创建文件chmod 644 "$stat_file" # 设置合理权限echo "已创建统计文件:$stat_file"
fi# 自动创建黑名单文件(如果不存在)
if [ ! -f "$blacklist" ]; thentouch "$blacklist"chmod 644 "$blacklist"echo "已创建黑名单文件:$blacklist"
fi# 修复:时间格式匹配Nginx日志(%b为英文月份缩写,如Aug/Jul)
start_time=$(date -d"$last_minutes minutes ago" +"%d/%b/%Y:%H:%M:%S")
stop_time=$(date +"%d/%b/%Y:%H:%M:%S")# 检查Nginx日志文件是否存在
if [ ! -f "$logfile/access.log" ]; thenecho "错误:Nginx日志文件 $logfile/access.log 不存在!"exit 1
fi# 1. 统计时间窗口内的IP访问次数(按次数降序)
tac "$logfile/access.log" | awk -v st="$start_time" -v et="$stop_time" '{t=substr($4,2); # 提取日志时间(去除开头的[符号)if(t>=st && t<=et){print $1} # 筛选时间范围内的IP
}' | sort | uniq -c | sort -nr > "$stat_file"# 2. 提取超过阈值的恶意IP
malicious_ips=$(awk -v threshold="$threshold" '$1 > threshold {print $2}' "$stat_file")# 3. 执行封禁(跳过已封禁的IP)
if [ -z "$malicious_ips" ]; thenecho "未发现超过阈值的IP(当前阈值:$threshold次/$last_minutes分钟)"exit 0
fifor ip in $malicious_ips; doif ! grep -q "^$ip$" "$blacklist"; then# 添加到黑名单echo "$ip" >> "$blacklist"# iptables封禁(拒绝该IP访问指定端口)iptables -I INPUT -p tcp -m multiport --dport "$block_ports" -s "$ip" -j DROPecho "已封禁恶意IP:$ip($last_minutes分钟内访问超过$threshold次)"elseecho "IP:$ip 已在黑名单中,无需重复封禁"fi
done
总结
log_ip_top10
是临时统计文件,核心作用是 “按访问次数排序,辅助筛选恶意 IP”。- 时间格式匹配是脚本生效的关键,必须确保
date
输出与 Nginx 日志格式一致。 - 替换时需重点调整 日志路径、时间格式、阈值、iptables 规则,并补充错误处理,避免脚本失效。
计划任务:
*/5 * * * * ~/iptables.sh >> ~/iptables.log 2>&1
~/iptalebs.log 2>&1
:将脚本的输出日志(包括错误信息)保存到 ~/iptables.log
,方便后续查看执行情况
五、用dirmap扫描
5.1 下载相关的依赖
pip3 install -r requirements.txt
下载的时候报错了:
5.2 缺少python的安装库:更新一下
sudo apt update && sudo apt install -y \libxml2-dev \libxslt1-dev \python3-dev \build-essential
5.3 报错缺少公钥文件,下载公钥
直接从公钥服务器获取并导入缺失的公钥:
# 1. 获取公钥(使用Ubuntu的密钥服务器,也可换为hkps://pgp.mit.edu)
sudo gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys ED65462EC8D5E4C5# 2. 将公钥导出到APT信任目录(兼容新老版本APT)
sudo gpg --export ED65462EC8D5E4C5 | sudo tee /etc/apt/trusted.gpg.d/kali.gpg > /dev/null
测试: