iptables封堵实验

发布于:2025-08-08 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、脚本功能分析

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
do
    echo $line >> $logfile/getip.txt  # 记录到getip.txt
    echo $line
    iptables  # 此处命令不完整!需补充封禁规则(如封禁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" ]; then
        echo "错误:日志文件 $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" ]; then
    touch "$stat_file"  # 创建文件
    chmod 644 "$stat_file"  # 设置合理权限
    echo "已创建统计文件:$stat_file"
fi

# 自动创建黑名单文件(如果不存在)
if [ ! -f "$blacklist" ]; then
    touch "$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" ]; then
    echo "错误: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" ]; then
    echo "未发现超过阈值的IP(当前阈值:$threshold次/$last_minutes分钟)"
    exit 0
fi

for ip in $malicious_ips; do
    if ! grep -q "^$ip$" "$blacklist"; then
        # 添加到黑名单
        echo "$ip" >> "$blacklist"
        # iptables封禁(拒绝该IP访问指定端口)
        iptables -I INPUT -p tcp -m multiport --dport "$block_ports" -s "$ip" -j DROP
        echo "已封禁恶意IP:$ip($last_minutes分钟内访问超过$threshold次)"
    else
        echo "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

测试:


网站公告

今日签到

点亮在社区的每一天
去签到