服务器日志分析完全指南:Nginx访问日志、GoAccess实时统计与异常流量识别

服务器日志是了解网站运行状况的第一手数据源:谁在访问、访问哪些页面、哪些请求报错、是否有恶意扫描……所有这些信息都藏在日志里。本文从日志格式配置到异常流量识别,给出完整的日志分析方案。

一、优化Nginx日志格式

# /etc/nginx/nginx.conf 中定义详细日志格式
http {
    log_format detailed '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" '
                        '$request_time $upstream_response_time '
                        '$http_x_forwarded_for';

    # JSON格式(便于日志分析工具解析)
    log_format json_log escape=json
        '{'
            '"time":"$time_iso8601",'
            '"remote_addr":"$remote_addr",'
            '"method":"$request_method",'
            '"uri":"$uri",'
            '"status":$status,'
            '"bytes_sent":$body_bytes_sent,'
            '"request_time":$request_time,'
            '"user_agent":"$http_user_agent",'
            '"referer":"$http_referer",'
            '"upstream_time":"$upstream_response_time"'
        '}';

    access_log /var/log/nginx/access.log detailed;
    # 或使用JSON格式:
    # access_log /var/log/nginx/access.json json_log;
}

二、基础日志分析命令(awk/grep)

<code"># 统计最多访问的IP(Top 20)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 统计最多访问的URL(Top 20)
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 统计各HTTP状态码数量
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 统计每小时请求量
awk '{print $4}' /var/log/nginx/access.log | cut -d: -f2 | sort | uniq -c

# 统计访问量最大的User-Agent(识别爬虫)
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 计算平均请求时间(需要detailed格式)
awk '{sum+=$NF; count++} END {print "平均响应时间: " sum/count "秒"}' /var/log/nginx/access.log

三、GoAccess:实时Web日志可视化

GoAccess是轻量级、高性能的实时Web日志分析工具,支持终端和HTML报表两种输出模式。

<code"># 安装GoAccess
apt install goaccess -y

# 实时终端分析(按q退出)
goaccess /var/log/nginx/access.log --log-format=COMBINED

# 生成HTML报表(输出到Web目录)
goaccess /var/log/nginx/access.log \
    --log-format=COMBINED \
    -o /var/www/html/report.html \
    --real-time-html

# 分析压缩日志文件
zcat /var/log/nginx/access.log.*.gz | goaccess --log-format=COMBINED -o report.html

# 合并多天日志分析
cat /var/log/nginx/access.log /var/log/nginx/access.log.1 | \
    goaccess --log-format=COMBINED -o report.html

GoAccess每日自动生成报表

<code"># /usr/local/bin/generate-report.sh
#!/bin/bash
DATE=$(date +%Y%m%d)
REPORT_DIR="/var/www/html/logs"
mkdir -p "$REPORT_DIR"

goaccess /var/log/nginx/access.log \
    --log-format=COMBINED \
    -o "$REPORT_DIR/report-$DATE.html" \
    --no-global-config

echo "报表已生成:$REPORT_DIR/report-$DATE.html"

# 每天凌晨1点生成前一天报表
echo "0 1 * * * root /usr/local/bin/generate-report.sh" >> /etc/crontab

四、识别恶意流量与异常行为

1. 识别高频访问IP(疑似CC攻击)

<code"># 统计当前5分钟内访问超过200次的IP
awk -v start="$(date -d '5 minutes ago' '+%d/%b/%Y:%H:%M')" \
    '$4 > "["start' /var/log/nginx/access.log | \
    awk '{print $1}' | sort | uniq -c | sort -rn | \
    awk '$1 > 200 {print "高频IP: "$2, "访问次数: "$1}'

2. 识别漏洞扫描器

<code"># 查找常见漏洞扫描特征(扫描特定路径)
grep -E "/(admin|wp-login|phpmyadmin|\.env|\.git|shell|eval|passwd)" \
    /var/log/nginx/access.log | \
    awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# 查找包含SQL注入特征的请求
grep -iE "(union|select|insert|drop|exec|eval|script)" \
    /var/log/nginx/access.log | head -20

3. 识别恶意爬虫

<code"># 查找伪装成正常浏览器但行为异常的爬虫
# 特征:同一IP短时间大量不同URL请求,UA是正常浏览器
awk 'NR==FNR{
    ip_count[$1]++;
    url_set[$1][$7]=1;
    next
}' /var/log/nginx/access.log | \
awk '{if(ip_count[$1]>500) print $1, ip_count[$1], length(url_set[$1])}'

4. 自动封禁恶意IP

<code">"#!/bin/bash
# /usr/local/bin/auto-ban.sh
# 自动封禁当前1小时内访问超过1000次的IP

THRESHOLD=1000
LOG="/var/log/nginx/access.log"
WHITELIST="127.0.0.1 你的办公室IP"

# 统计高频IP
HIGH_FREQ_IPS=$(awk -v start="$(date -d '1 hour ago' '+%d/%b/%Y:%H')" \
    '$4 ~ "^\\["start' "$LOG" | \
    awk '{print $1}' | sort | uniq -c | sort -rn | \
    awk -v t="$THRESHOLD" '$1 > t {print $2}')

for IP in $HIGH_FREQ_IPS; do
    # 跳过白名单IP
    if echo "$WHITELIST" | grep -q "$IP"; then
        continue
    fi
    
    # 检查是否已封禁
    if ! ufw status | grep -q "$IP"; then
        ufw deny from "$IP" to any
        echo "$(date): 已封禁 $IP" >> /var/log/auto-ban.log
    fi
done

五、错误日志分析

<code"># 查看Nginx错误日志
tail -f /var/log/nginx/error.log

# 统计错误类型
awk '{print $8}' /var/log/nginx/error.log | sort | uniq -c | sort -rn | head -20

# 查找502错误(后端服务器问题)
grep "upstream" /var/log/nginx/error.log | \
    grep "failed" | tail -50

# 查找PHP-FPM相关错误
grep -E "connect\(\)|no live|while reading" /var/log/nginx/error.log | tail -20

六、日志轮转配置

<code"># /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 30          # 保留30天
    compress           # 压缩旧日志
    delaycompress      # 延迟一天再压缩(保持最近一份可读)
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        # 日志轮转后重新打开日志文件
        nginx -s reopen
    endscript
}

七、总结

日志分析是服务器运维不可缺少的能力:定期看GoAccess报表了解流量趋势,设置自动封禁脚本应对CC攻击,分析错误日志快速定位故障根源。IDC.Net的香港VPSNVMe SSD写入速度快,高流量站点的日志写入不会成为性能瓶颈,是稳定记录分析数据的理想环境。

THE END