很多站长等网站被入侵、被挂马了,才想起来查日志。其实攻击者早在得手之前,就已在你的 Nginx 访问日志里留下大量痕迹:目录爆破、SQL 注入探测、后台口令爆破……特征非常明显,只要会看日志,就能在攻击得手前发现并封堵。本文以宝塔面板 + Nginx 环境为例,从日志位置、攻击特征识别、自动化告警到 fail2ban 联动封禁,给出一套可直接落地的日志分析方案。
一、日志在哪?看懂一行访问日志
Nginx 访问日志默认在 /www/wwwlogs/(宝塔面板)或 /var/log/nginx/(源码编译)目录下,以「站点域名 + 日期」命名,例如 www.zhujib.com.log。先确认日志在正常写入:
tail -n 5 /www/wwwlogs/www.zhujib.com.log
默认 combined 格式的日志长这样:
103.44.212.111 - - [21/Aug/2026:03:12:44 +0800] "GET /wp-login.php HTTP/1.1" 404 162 "-" "Mozilla/5.0"
字段依次为:IP → 时间 → 请求方法/路径/协议 → 状态码 → 响应大小 → Referer → User-Agent。日志分析就是围绕这几个字段做统计与特征匹配。若发现日志里只有 IP 没有域名,说明多站点未分别记录日志,建议在站点配置中显式指定 access_log 路径,避免攻击流量混在一起难以定位。
二、三招快速揪出攻击者
1. 按 IP 统计请求量,锁定异常高频访问
正常用户访问频率有上限,单 IP 一天几万次,基本可判定是扫描器或爬虫。用 awk 按 IP 分组统计:
awk '{print $1}' /www/wwwlogs/www.zhujib.com.log | sort | uniq -c | sort -rn | head -20
对异常 IP 再查它访问了什么路径:
grep "^103.44.212.111" /www/wwwlogs/www.zhujib.com.log | awk '{print $6}' | sort | uniq -c | sort -rn | head -20
如果看到大量 /wp-login.php、/.env、/.git/config、/phpmyadmin/ 这类路径,基本锁定是自动化攻击工具,直接在防火墙层封禁即可。
2. 统计 404 请求,识别目录爆破与漏洞扫描
正常访客不会访问一堆不存在的路径,404 比例畸高说明有人在探测站点结构:
# 404 最多的前 10 个 IP
grep '" 404 ' /www/wwwlogs/www.zhujib.com.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# 被请求最多的不存在的路径
grep '" 404 ' /www/wwwlogs/www.zhujib.com.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
同时留意 403 状态码:大量 403 说明扫描器在试探受保护目录(如 /admin、/backup)。
3. 特征关键字匹配注入与暴力破解
SQL 注入探测会在 URL 或 UA 中携带 union select、sleep(、information_schema 等特征;暴力破解表现为短时间内对登录接口的连续请求。一条 grep 全部捞出来:
grep -E "union[[:space:]]+select|sleep\(|information_schema|\.\./\.\./|select[[:space:]]+1,2,3" /www/wwwlogs/www.zhujib.com.log | head -20
# 统计针对 wp-login.php 的爆破 IP 与尝试次数
grep "wp-login.php" /www/wwwlogs/www.zhujib.com.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
注意:很多扫描器会把攻击载荷 URL 编码(如 %27%20or%20%271%27%3D%271),日志里看不到明文关键字,直接匹配会漏掉相当一部分注入流量。更省事的做法是给站点套一层 WAF(如百度云防护),把解码、规则匹配交给 WAF,日志分析只负责兜底。
三、自动化:定时巡检 + 告警 + 联动封禁
1. 写一个日志巡检脚本
手动敲命令只能发现问题,自动化才能坚持。把下面脚本存为 /root/log_check.sh 并赋予执行权限:
#!/bin/bash
LOG=/www/wwwlogs/www.zhujib.com.log
# 1) 单 IP 请求量超过 2000 次判定为异常
awk '{print $1}' $LOG | sort | uniq -c | sort -rn | awk '$1>2000{print $2" "$1}' > /tmp/hot_ip.txt
# 2) 含有注入/扫描特征的行
grep -E "union[[:space:]]+select|information_schema|\.\./\.\./" $LOG > /tmp/attack_lines.txt
# 3) 有异常则发告警(换成你的企业微信/钉钉机器人地址)
if [ -s /tmp/hot_ip.txt ] || [ -s /tmp/attack_lines.txt ]; then
curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的KEY" -H "Content-Type: application/json" -d "{"msgtype":"text","text":{"content":"站点检测到异常流量,请查看 /tmp/hot_ip.txt"}}"
fi
加入 crontab,每天凌晨跑一次:
chmod +x /root/log_check.sh
crontab -e
# 追加一行:
0 3 * * * /root/log_check.sh
2. 与 fail2ban 联动,发现即封禁
日志分析发现问题后,最好的响应是自动封禁。安装并启用 fail2ban 的 Nginx 过滤:
# Debian/Ubuntu
apt install -y fail2ban
# CentOS/宝塔
yum install -y fail2ban
cat > /etc/fail2ban/jail.local <<'EOF'
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /www/wwwlogs/www.zhujib.com.log
maxretry = 5
bantime = 86400
EOF
systemctl restart fail2ban
fail2ban 在 maxretry 次匹配后自动把 IP 封禁 bantime 秒,与巡检脚本配合形成「日志识别 → 告警通知 → 自动封禁」的闭环。确认规则生效:
fail2ban-client status nginx-botsearch
iptables -L -n | grep f2b
总结
日志分析是服务器安全最基础也最有效的一环,成本几乎为零,却能让你在攻击得手前看到敌人动向。核心就三件事:知道日志在哪、认识攻击特征、把分析自动化。建议按「日志巡检脚本 + fail2ban + WAF」三层组合落地:本地日志兜底识别,fail2ban 快速封禁,前置 WAF 处理解码与规则匹配。如果你不想自己维护这条链路,也可以选择速度网络的服务器安全托管服务,由专业团队提供日志审计、安全加固与 7×24 小时应急响应。
