[linux][shell]通过分析 Nginx 的访问日志,检测异常 IP 地址并使用iptables 将其封禁_go 日志log分析异常ip封
这段脚本的作用是通过分析 Nginx 的访问日志,检测异常的 IP 地址,并使用 iptables
封禁这些 IP。
#!/bin/bash# 配置变量LOG_FILE=\"/usr/local/nginx/logs/access.log\"THRESHOLD=10DROP_LOG_FILE=\"/tmp/drop_ip.log\"DATE=$(date +\"%d/%b/%Y:%H:%M\")# 检测异常 IPABNORMAL_IP=$(tail -n5000 \"$LOG_FILE\" | grep \"$DATE\" | awk \'{a[$1]++} END {for(i in a) if(a[i]>\'$THRESHOLD\') print i}\')# 封禁异常 IPfor IP in $ABNORMAL_IP; do # 检查 IP 是否已经被封禁 if ! iptables -C INPUT -s \"$IP\" -j DROP &> /dev/null; then # 封禁 IP iptables -I INPUT -s \"$IP\" -j DROP echo \"$(date +\'%F_%T\') $IP - Access count exceeded threshold ($THRESHOLD)\" >> \"$DROP_LOG_FILE\" fidone
以下是脚本的详细解析和一些需要注意的地方:
脚本功能
-
配置变量:
-
LOG_FILE
:指定 Nginx 的访问日志文件路径。 -
THRESHOLD
:设置访问次数的阈值,超过此值的 IP 将被认定为异常。 -
DROP_LOG_FILE
:记录被封禁 IP 的日志文件路径。 -
DATE
:获取当前时间,格式为日/月/年:时:分
,用于筛选日志中当前时间的记录。
-
-
检测异常 IP:
-
使用
tail -n5000 \"$LOG_FILE\"
获取日志文件的最后 5000 行。 -
使用
grep \"$DATE\"
筛选出当前时间的记录。 -
使用
awk
统计每个 IP 的访问次数,并筛选出访问次数超过阈值的 IP。
-
-
封禁异常 IP:
-
遍历检测到的异常 IP。
-
使用
iptables -C INPUT -s \"$IP\" -j DROP
检查该 IP 是否已经被封禁。 -
如果未被封禁,则使用
iptables -I INPUT -s \"$IP\" -j DROP
将其封禁,并将封禁信息记录到DROP_LOG_FILE
中。
-
注意事项
-
日志格式依赖:
-
脚本假设 Nginx 的日志格式是标准的 Combined Log Format,其中第一个字段是 IP 地址。如果日志格式不同,需要调整
awk
的字段索引。
-
-
时间格式匹配:
-
DATE
的格式需要与 Nginx 日志中的时间格式完全匹配。如果日志中的时间格式不同(例如包含毫秒或时区信息),脚本可能无法正确筛选记录。
-
-
权限问题:
-
脚本需要以 root 用户运行,因为
iptables
命令需要管理员权限。
-
-
性能问题:
-
如果日志文件非常大,
tail -n5000
和grep
操作可能会消耗较多资源。可以考虑优化日志处理方式,例如定期清理日志或使用更高效的数据处理工具。
-
-
误封风险:
-
脚本简单地根据访问次数封禁 IP,可能会误封正常用户(例如爬虫或高频访问的合法用户)。建议结合其他检测机制(如访问频率、请求类型等)来提高准确性。
-
-
日志记录:
-
封禁日志记录到
/tmp/drop_ip.log
,但/tmp
目录可能会被定期清理。建议将日志存储到更安全的路径,例如/var/log
。
-
改进建议
-
日志格式检查:在脚本开头检查日志文件是否存在以及是否符合预期格式。
-
动态阈值:根据流量情况动态调整阈值,而不是固定值。
-
白名单机制:维护一个白名单,避免误封重要 IP。
-
持久化封禁规则:使用
iptables-save
和iptables-restore
保存和恢复规则,避免系统重启后规则丢失。 -
日志清理:定期清理封禁日志文件,避免文件过大。