问题解构
解决需求的核心在于利用 **Linux 系统下的 Bash 脚本**配合 **iptables 防火墙工具**,实现对特定 IP 地址的"彻底封禁"。这里的"彻底封禁"在网络运维层面通常意味着:
-
**阻断连接**:利用 iptables 丢弃来自目标 IP 的所有数据包。
-
**持久化**:通过脚本机制确保持久生效,防止重启失效或自动解封。
-
**自动化防御**:结合日志监控,自动识别恶意行为(如 SSH 暴力破解、SQL 注入尝试)并触发封禁。
方案推演
-
**基础封禁逻辑**:使用 `iptables` 的 `DROP` 目标,静默丢弃数据包,不返回拒绝信息,增加攻击者的探测难度。
-
**自动化触发机制**:编写 Bash 脚本,定期(如每分钟)分析系统日志(如 `/var/log/secure` 或 `/var/log/httpd/access_log`),统计特定 IP 的恶意请求频率。一旦超过设定阈值(如 1 分钟内尝试 5 次密码错误),自动调用 iptables 规则封禁该 IP。
-
**服务端锁定与持久化**:虽然无法物理"锁死"服务器硬件,但可以通过脚本将封禁规则写入系统配置文件或使用 `ipset` 工具优化大规模 IP 列表的管理效率,实现逻辑上的永久封禁,直到管理员手动解除 。
-
**全栈协议拦截**:iptables 默认作用于网络层和传输层,通过封禁 IP 源地址,自然切断了该 IP 对所有上层协议(HTTP、HTTPS、SSH 等)的访问能力,无需针对每种协议单独写规则。
iptables 与 Bash 结合封禁 IP 的具体实现
以下方案分为两个部分:一是基础的 Bash 脚本实现 IP 自动封禁(以 SSH 防护为例),二是针对 Web 攻击(HTTP/HTTPS/SQL 注入)的日志分析与封禁逻辑。
1. 自动封禁 SSH 暴力破解 IP 的脚本
此脚本通过监控 SSH 登录日志,识别频繁失败的 IP 并将其加入防火墙黑名单。
```bash
#!/bin/bash
==========================================
功能:自动封禁SSH暴力破解IP
环境:Linux CentOS/Ubuntu
==========================================
定义日志文件路径
LOG_FILE="/var/log/ssh_block.log"
定义封禁阈值:失败多少次后封禁
FAILURE_THRESHOLD=5
定义检查间隔(秒)
CHECK_INTERVAL=30
主循环
while true; do
获取当前时间点之前的失败登录尝试次数统计
过滤出"Failed password"的日志,提取IP,排序并统计出现次数
FAILED_IPS=(grep "Failed password" /var/log/secure \| awk '{print (NF-3)}' | sort | uniq -c | awk "{if(\1\>FAILURE_THRESHOLD) print \$2}")
for IP in $FAILED_IPS; do
检查该IP是否已经在iptables中存在
EXISTING_RULE=(iptables -L INPUT -n \| grep IP | grep DROP)
if [ -z "$EXISTING_RULE" ]; then
echo "[(date)\] 检测到恶意IP: IP,正在执行封禁..." >> $LOG_FILE
执行封禁命令:DROP所有来自该IP的数据包
这将彻底切断该IP的SSH、HTTP等所有连接
iptables -A INPUT -s $IP -j DROP
记录封禁日志
echo "[(date)\] IP IP 已被封禁。" >> $LOG_FILE
fi
done
休眠指定时间后再次检查
sleep $CHECK_INTERVAL
done
```
*代码解析:该脚本通过 `awk` 提取日志中的 IP 地址,利用 `uniq -c` 统计失败次数。一旦超过阈值,使用 `iptables -A INPUT -s $IP -j DROP` 命令将该 IP 的所有流量丢弃 。*
2. 封禁 Web 恶意访问(HTTP/HTTPS/SQL注入)
针对 Web 服务的攻击(如 SQL 注入、频繁扫描),通常需要分析 Web 服务器的访问日志(如 Nginx 或 Apache 的 access.log)。以下脚本展示了如何封禁在极短时间内发起大量请求的 IP 。
```bash
#!/bin/bash
==========================================
功能:基于Web日志封禁高频恶意访问IP(防御SQL注入/CC攻击)
==========================================
日志文件路径 (根据实际环境修改,如 /var/log/nginx/access.log)
LOG_FILE="/var/log/httpd/access_log"
封禁时间窗口:最近1分钟
LAST_MINUTES=1
封禁阈值:1分钟内请求超过100次
MAX_REQUESTS=100
计算时间范围
START_TIME=(date -d "LAST_MINUTES minutes ago" +"%d/%m/%Y:%H:%M:%S")
END_TIME=$(date +"%d/%m/%Y:%H:%M:%S")
echo "正在分析 START_TIME 到 END_TIME 之间的日志..."
提取在时间窗口内请求次数超过阈值的IP
tac命令倒序读取日志,提高效率;awk过滤时间段并统计IP频次
BAD_IPS=(tac LOG_FILE | awk -v st="START_TIME" -v et="END_TIME" \
'{t=substr(4,2); if(t\>=st \&\& t\<=et) {print 1}}' \
| sort | uniq -c | awk "{if(\1\>MAX_REQUESTS) print \$2}")
for IP in $BAD_IPS; do
echo "发现高频攻击IP: $IP"
使用 iptables 封禁该 IP
这里的规则同样适用于HTTP和HTTPS,因为封禁的是IP层
iptables -I INPUT -s $IP -j DROP
echo "IP $IP 已被加入防火墙黑名单。"
done
```
*代码解析:此脚本通过分析 Web 日志中的时间戳和 IP 地址,定位出在极短时间内发起大量请求(可能是 SQL 注入扫描或 CC 攻击)的源 IP,并直接调用 iptables 进行拦截 。*
3. 使用 ipset 优化大规模封禁(推荐)
当需要封禁的 IP 数量很大(如封禁整个国家或地区的 IP 段)时,直接使用 iptables 会严重影响性能。推荐使用 `ipset` 结合 iptables 进行管理 。
```bash
#!/bin/bash
==========================================
功能:使用 ipset 批量封禁 IP 段(高效管理)
==========================================
检查是否为root用户
if [[ $EUID -ne 0 ]]; then
echo "Error: 此脚本必须以 root 权限运行!" 1>&2
exit 1
fi
创建一个名为 "blacklist" 的 IP 集合(如果不存在)
ipset create blacklist hash:net hashsize 4096 2>/dev/null
假设我们有一个包含恶意 IP 的文件 bad_ips.txt
FILE="bad_ips.txt"
if [ -f "$FILE" ]; then
读取文件中的 IP 并添加到 ipset 集合中
while read IP; do
ipset -A blacklist $IP
done < $FILE
echo "IP 列表已加载到 ipset。"
在 iptables 中引用该集合
这一条规则即可封禁集合内所有 IP
如果规则已存在则忽略,避免重复添加
if ! iptables -C INPUT -m set --match-set blacklist src -j DROP 2>/dev/null; then
iptables -A INPUT -m set --match-set blacklist src -j DROP
echo "iptables 规则已更新,匹配 blacklist 集合。"
else
echo "iptables 规则已存在。"
fi
else
echo "错误:未找到 $FILE 文件"
fi
```
*代码解析:`ipset` 允许将 IP 地址存储在一个集合中,iptables 只需要一条规则即可匹配该集合内的所有 IP。这种方法在处理大量 IP(如针对特定国家代码的 IP 段封禁)时,效率远高于逐条添加 iptables 规则 。*
总结与注意事项
-
**彻底性**:通过上述 Bash 脚本结合 `iptables -j DROP`,可以实现从网络层彻底阻断目标 IP 的所有数据包,无论是 SSH、HTTP 还是 HTTPS 流量都无法通过。
-
**持久化保存**:上述脚本运行时的规则在系统重启后会失效。为确保"永久"封禁,需要执行 `service iptables save`(CentOS 6)或 `iptables-save > /etc/iptables/rules.v4`(Ubuntu/Debian)将规则保存到配置文件中 。
-
**误报处理**:在设置阈值(如 `FAILURE_THRESHOLD`)时需谨慎,过低的阈值可能导致误封正常用户。建议先在测试环境运行,观察日志后再部署到生产环境。