1. 1. 28-日志分析工具与技巧
    1. 1.1. 一、GoAccess — 实时 Web 日志分析器
      1. 1.1.1. 1.1 工具简介
      2. 1.1.2. 1.2 安装方法
      3. 1.1.3. 1.3 命令行实时分析
      4. 1.1.4. 1.4 生成 HTML 报告
      5. 1.1.5. 1.5 自定义日志格式
      6. 1.1.6. 1.6 应急场景:快速分析攻击者访问模式
    2. 1.2. 二、lnav — 终端日志浏览器
      1. 1.2.1. 2.1 工具简介与安装
      2. 1.2.2. 2.2 基本用法
      3. 1.2.3. 2.3 过滤和搜索
      4. 1.2.4. 2.4 内置 SQL 查询功能(重要!)
    3. 1.3. 三、ELK Stack 简介
      1. 1.3.1. 3.1 架构概述
      2. 1.3.2. 3.2 在应急响应中的定位
      3. 1.3.3. 3.3 应急响应场景快速搭建
    4. 1.4. 四、awk/grep/sed One-Liners 精华集
      1. 1.4.1. 4.1 按 IP 统计访问量(Top 20)
      2. 1.4.2. 4.2 按 URL 统计访问量
      3. 1.4.3. 4.3 按 User-Agent 统计
      4. 1.4.4. 4.4 按时间段统计访问量
      5. 1.4.5. 4.5 提取所有 POST 请求
      6. 1.4.6. 4.6 SQL 注入检测模式
      7. 1.4.7. 4.7 目录遍历检测
      8. 1.4.8. 4.8 Webshell 访问特征
      9. 1.4.9. 4.9 按返回状态码统计
      10. 1.4.10. 4.10 提取所有出现的 IP 地址
      11. 1.4.11. 4.11 SSH 暴力破解 IP 统计
      12. 1.4.12. 4.12 按小时统计失败登录
      13. 1.4.13. 4.13 提取 sudo 命令
      14. 1.4.14. 4.14 时间线生成
      15. 1.4.15. 4.15 综合分析命令(额外实用补充)
    5. 1.5. 五、jq 处理 JSON 日志
      1. 1.5.1. 5.1 jq 简介与安装
      2. 1.5.2. 5.2 基本用法
      3. 1.5.3. 5.3 应急分析场景
      4. 1.5.4. 5.4 jq 与其他工具的组合
    6. 1.6. 六、实战演练:分析包含攻击痕迹的 access.log
      1. 1.6.1. 6.1 场景描述
      2. 1.6.2. 6.2 分析流程
      3. 1.6.3. 6.3 工具选择建议
      4. 1.6.4. 6.4 注意事项
    7. 1.7. 参考与延伸

Linux应急响应 - 28 日志分析工具

28-日志分析工具与技巧

在应急响应中,日志是最关键的证据来源。掌握高效的日志分析工具,能让你在海量日志中快速定位攻击痕迹。本章介绍从命令行到 GUI 的完整日志分析工具链。

相关章节:03-日志分析基础 | 12-Nginx与Apache应急

一、GoAccess — 实时 Web 日志分析器

1.1 工具简介

GoAccess 是一款开源的 实时 Web 日志分析器 和交互式查看器

可在终端中直接运行,也可生成独立的 HTML 报告

支持 Apache、Nginx、Amazon S3、CloudFront 等常见日志格式

特点:速度极快(C 语言编写)、无需额外依赖、支持实时流式分析

1.2 安装方法

Ubuntu / Debian 系统

1
2
3
4
5
6
7
8
9
10
11
# 添加官方 PPA(推荐,获取最新版本)
echo "deb https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
wget -O - https://deb.goaccess.io/gnupg.key | sudo apt-key add -
sudo apt update
sudo apt install goaccess -y

# 或者直接从仓库安装(版本可能较旧)
sudo apt install goaccess -y

# 验证安装
goaccess --version

CentOS / RHEL 系统

1
2
3
4
5
6
7
8
9
10
11
# EPEL 仓库安装
sudo yum install epel-release -y
sudo yum install goaccess -y

# 或从源码编译(获取最新版本)
sudo yum install gcc make ncurses-devel geoip-devel tokyocabinet-devel -y
wget https://tar.goaccess.io/goaccess-1.9.3.tar.gz
tar -xzf goaccess-1.9.3.tar.gz
cd goaccess-1.9.3
./configure --enable-utf8 --enable-geoip=mmdb
make && sudo make install

从源码编译(通用方法)

1
2
3
4
5
6
7
8
# 安装依赖
sudo apt install build-essential libncursesw5-dev libmaxminddb-dev -y

git clone https://github.com/allinurl/goaccess.git
cd goaccess
autoreconf -fiv
./configure --enable-utf8 --enable-geoip=mmdb
make && sudo make install

1.3 命令行实时分析

基本交互式分析

1
2
3
4
5
6
7
8
9
10
11
# 分析 Nginx 访问日志(自动检测格式)
goaccess /var/log/nginx/access.log -c

# 指定日志格式为 COMBINED(最常见)
goaccess /var/log/nginx/access.log --log-format=COMBINED

# 分析 Apache 日志
goaccess /var/log/apache2/access.log --log-format=COMBINED

# 实时跟踪日志(类似 tail -f 的效果)
tail -f /var/log/nginx/access.log | goaccess --log-format=COMBINED -

交互界面中的快捷键:

快捷键 功能
TAB 切换面板
ENTER 展开当前面板
q 退出
/ 搜索
0-9 快速跳转到对应面板
s 排序方式切换

1.4 生成 HTML 报告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 生成静态 HTML 报告
goaccess /var/log/nginx/access.log -o /tmp/report.html --log-format=COMBINED

# 生成实时刷新的 HTML 报告(WebSocket)
goaccess /var/log/nginx/access.log -o /tmp/report.html --log-format=COMBINED --real-time-html

# 分析多个日志文件并生成报告
goaccess /var/log/nginx/access.log /var/log/nginx/access.log.1 -o /tmp/report.html --log-format=COMBINED

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

# 生成 JSON 格式输出(便于程序处理)
goaccess /var/log/nginx/access.log -o /tmp/report.json --log-format=COMBINED

# 生成 CSV 格式输出
goaccess /var/log/nginx/access.log -o /tmp/report.csv --log-format=COMBINED

生成的 HTML 报告会包含以下面板:

总体请求统计、唯一访客、请求文件、404 页面

访客 IP 排行、操作系统、浏览器

来源 URL、HTTP 状态码分布

地理位置(如果启用了 GeoIP)

1.5 自定义日志格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 如果你的 Nginx 使用自定义 log_format,需要手动指定
# 假设 Nginx 配置为:
# log_format custom '$remote_addr - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';

goaccess /var/log/nginx/access.log \
--log-format='%h - [%d:%t %^] "%r" %s %b "%R" "%u" %T' \
--date-format='%d/%b/%Y' \
--time-format='%H:%M:%S'

# 常用格式变量:
# %h = 客户端 IP
# %d = 日期
# %t = 时间
# %r = 请求行(方法 + URI + 协议)
# %s = HTTP 状态码
# %b = 响应大小
# %R = Referer
# %u = User-Agent
# %T = 请求耗时(秒)
# %^ = 忽略字段

1.6 应急场景:快速分析攻击者访问模式

1
2
3
4
5
6
7
8
9
10
11
12
13
# 场景:发现疑似入侵,需要快速了解攻击者行为

# 1. 过滤特定 IP 的所有访问,生成报告
grep "192.168.1.100" /var/log/nginx/access.log | goaccess --log-format=COMBINED -o /tmp/attacker_report.html -

# 2. 分析特定时间段的日志
awk '$4 >= "[02/Apr/2026:10:00" && $4 <= "[02/Apr/2026:12:00"' /var/log/nginx/access.log | goaccess --log-format=COMBINED -o /tmp/timerange.html -

# 3. 只分析可疑的 POST 请求
grep '"POST ' /var/log/nginx/access.log | goaccess --log-format=COMBINED -o /tmp/post_requests.html -

# 4. 排除内部 IP,只看外部访问
grep -v -E "^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)" /var/log/nginx/access.log | goaccess --log-format=COMBINED -o /tmp/external.html -

二、lnav — 终端日志浏览器

2.1 工具简介与安装

lnav(Log File Navigator)是一个增强型终端日志查看器

自动识别常见日志格式、语法高亮、支持 SQL 查询

可以同时打开多个日志文件,按时间线合并显示

1
2
3
4
5
6
7
8
9
10
11
12
# Ubuntu / Debian
sudo apt install lnav -y

# CentOS / RHEL
sudo yum install epel-release -y
sudo yum install lnav -y

# macOS
brew install lnav

# 验证
lnav --version

2.2 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看单个日志文件
lnav /var/log/syslog

# 同时查看多个文件(自动按时间线合并)
lnav /var/log/syslog /var/log/auth.log /var/log/kern.log

# 查看目录下所有日志
lnav /var/log/

# 查看压缩日志(自动解压)
lnav /var/log/syslog.1.gz

# 从 stdin 读取
journalctl -u sshd | lnav

常用快捷键:

快捷键 功能
e / E 跳转到下一个/上一个 Error
w / W 跳转到下一个/上一个 Warning
n / N 跳转到下一个/上一个搜索结果
/ 搜索(正则表达式)
TAB 切换文件视图
i 显示直方图视图
; 进入 SQL 查询模式
p 切换 Pretty-Print 模式
CTRL+w 切换自动换行
g / G 跳转到开头/末尾

2.3 过滤和搜索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 在 lnav 界面中:

# 搜索(按 / 进入搜索模式)
/Failed password
/192\.168\.1\.100
/SQL|injection|union|select

# 过滤(按 : 进入命令模式)
:filter-in Failed password # 只显示包含关键词的行
:filter-out systemd # 排除包含关键词的行
:reset-session # 重置所有过滤器
:set-min-log-level error # 只显示 error 及以上级别

# 标记书签(按 m 标记当前行)
# 按 u / U 在书签间跳转

2.4 内置 SQL 查询功能(重要!)

lnav 将日志自动解析为结构化数据,可用 SQL 查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 按 ; 进入 SQL 模式

# 统计每个 IP 的访问次数(syslog)
;SELECT log_hostname, count(*) as cnt FROM syslog_log GROUP BY log_hostname ORDER BY cnt DESC

# 统计每小时的日志量
;SELECT strftime('%Y-%m-%d %H:00', log_time) as hour, count(*) as cnt FROM syslog_log GROUP BY hour ORDER BY hour

# 查找特定时间范围的日志
;SELECT * FROM syslog_log WHERE log_time BETWEEN '2026-04-01 10:00:00' AND '2026-04-01 12:00:00'

# 统计日志级别分布
;SELECT log_level, count(*) as cnt FROM syslog_log GROUP BY log_level ORDER BY cnt DESC

# 查找包含关键词的日志
;SELECT log_time, log_body FROM syslog_log WHERE log_body LIKE '%Failed password%' ORDER BY log_time

这些查询结果可以直接在终端中以表格形式显示,非常直观

三、ELK Stack 简介

3.1 架构概述

ELK Stack 由三个核心组件组成:

Elasticsearch:分布式搜索和分析引擎,负责存储和检索日志数据

Logstash:数据收集和处理管道,负责日志的采集、解析、转换

Kibana:可视化平台,提供 Web 界面进行数据分析和展示

现代 ELK Stack 通常还包括:

Filebeat:轻量级日志采集器(替代 Logstash 做采集)

Elastic Agent:统一的端点代理

数据流向:

1
2
日志文件 → Filebeat/Logstash → Elasticsearch → Kibana
(采集/解析) (存储/索引) (可视化)

3.2 在应急响应中的定位

集中化日志分析:将多台服务器的日志统一采集到一处

快速搜索:Elasticsearch 的全文搜索能力,可在 TB 级日志中秒级返回结果

可视化:Kibana 的仪表板可以直观展示攻击模式

时间线分析:按时间维度关联不同来源的日志

适用场景:

大规模事件(涉及多台主机)

需要长期日志留存和分析

需要团队协作分析

不适用场景:

单台主机的快速排查(用 GoAccess/lnav 更快)

资源有限的环境(ELK 需要大量内存)

3.3 应急响应场景快速搭建

1
2
3
4
# 使用 Docker Compose 快速搭建(用于事件分析,非生产部署)
# 注意:至少需要 4GB 内存

mkdir -p /opt/elk-ir && cd /opt/elk-ir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# docker-compose.yml
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data

kibana:
image: docker.elastic.co/kibana/kibana:8.12.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch

logstash:
image: docker.elastic.co/logstash/logstash:8.12.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
- /var/log:/host-logs:ro
depends_on:
- elasticsearch

volumes:
es-data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Logstash 配置文件 logstash.conf
cat > logstash.conf << 'CONF'
input {
file {
path => "/host-logs/nginx/access.log"
start_position => "beginning"
type => "nginx-access"
}
file {
path => "/host-logs/auth.log"
start_position => "beginning"
type => "auth"
}
}

filter {
if [type] == "nginx-access" {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
geoip {
source => "clientip"
}
}
}

output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "ir-logs-%{+YYYY.MM.dd}"
}
}
CONF

# 启动
docker-compose up -d

# 等待启动完成后访问 Kibana
echo "Kibana: http://localhost:5601"

搭建完成后在 Kibana 中创建 Index Pattern ir-logs-*,即可开始搜索分析

四、awk/grep/sed One-Liners 精华集

这是应急响应中最常用的 20 个日志分析命令。建议收藏,实战中直接套用。

4.1 按 IP 统计访问量(Top 20)

1
2
3
4
5
6
7
8
9
10
# 适用于 Nginx/Apache combined 格式日志
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 说明:$1 是日志第一个字段(客户端 IP)
# sort | uniq -c 统计每个 IP 出现次数
# sort -rn 按数量降序排列
# 输出示例:
# 15234 192.168.1.100
# 8921 10.0.0.5
# 3456 203.0.113.50

4.2 按 URL 统计访问量

1
2
3
4
5
# 统计请求 URL Top 20
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 只统计非静态资源的 URL
awk '{print $7}' /var/log/nginx/access.log | grep -v -E '\.(css|js|jpg|png|gif|ico|svg|woff)' | sort | uniq -c | sort -rn | head -20

4.3 按 User-Agent 统计

1
2
3
4
5
# 提取 User-Agent 并统计(combined 日志格式)
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 查找可疑的 User-Agent(扫描器、bot 等)
awk -F'"' '{print $6}' /var/log/nginx/access.log | grep -iE '(sqlmap|nikto|nmap|masscan|dirbuster|gobuster|nuclei|xray|awvs|nessus|burp|curl|wget|python|scanner)' | sort | uniq -c | sort -rn

4.4 按时间段统计访问量

1
2
3
4
5
6
7
8
# 按小时统计请求量(发现异常流量高峰)
awk '{print substr($4,2,14)}' /var/log/nginx/access.log | awk -F: '{print $1":"$2":00"}' | sort | uniq -c | sort -k2

# 按分钟统计(更精细的粒度)
awk '{print substr($4,2,17)}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -30

# 统计某个时间段的请求量
awk '$4 >= "[02/Apr/2026:10:00" && $4 <= "[02/Apr/2026:12:00"' /var/log/nginx/access.log | wc -l

4.5 提取所有 POST 请求

1
2
3
4
5
6
7
8
# 提取所有 POST 请求及其 URL
grep '"POST ' /var/log/nginx/access.log | awk '{print $1, $7}' | sort | uniq -c | sort -rn | head -20

# POST 请求的完整日志行
grep '"POST ' /var/log/nginx/access.log

# 查找向可疑路径发送 POST 的请求
grep '"POST ' /var/log/nginx/access.log | grep -iE '(upload|shell|cmd|exec|eval|admin|login)'

4.6 SQL 注入检测模式

1
2
3
4
5
6
7
8
# 在访问日志中检测 SQL 注入尝试
grep -iE "(union\+select|union%20select|select\+from|select%20from|or\+1=1|or%201=1|and\+1=1|'--|%27--|benchmark\(|sleep\(|load_file|into\+outfile|information_schema|concat\(|group_concat)" /var/log/nginx/access.log

# 更精确的正则(减少误报)
awk '/(union.*select|select.*from.*where|or\+1=1|%27\+or|sleep\([0-9]+\)|benchmark\([0-9]+|load_file\(|into\+(out|dump)file)/i' /var/log/nginx/access.log

# 统计 SQL 注入来源 IP
grep -iE "(union.*select|or\+1=1|sleep\(|benchmark\()" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn

4.7 目录遍历检测

1
2
3
4
5
# 检测目录遍历攻击尝试
grep -E '(\.\.\/|\.\.%2[fF]|%2e%2e%2f|\.\.\\|%252e%252e)' /var/log/nginx/access.log

# 统计目录遍历攻击来源
grep -E '(\.\.\/|\.\.%2[fF])' /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn

4.8 Webshell 访问特征

1
2
3
4
5
6
7
8
# 检测可能的 Webshell 访问
grep -iE '(cmd=|shell=|exec=|system\(|passthru|eval\(|base64_decode|assert\(|phpinfo|whoami|id%20|cat%20/etc|/bin/bash|/bin/sh)' /var/log/nginx/access.log

# 查找对可疑文件名的访问
grep -iE '\.(php|jsp|asp|aspx|cgi)\?' /var/log/nginx/access.log | grep -iE '(cmd|shell|hack|backdoor|spy|c99|r57|b374k|weevely|antsword|behinder|godzilla|ice|tunnel)'

# 查找短时间内对单个 PHP 文件的大量访问(可能是 Webshell 交互)
awk '$7 ~ /\.php/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

4.9 按返回状态码统计

1
2
3
4
5
6
7
8
9
10
11
# 统计 HTTP 状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 查找所有 500 错误
awk '$9 == 500 {print $0}' /var/log/nginx/access.log

# 查找所有 403 Forbidden(可能是扫描行为)
awk '$9 == 403' /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# 大量 404 的 IP(目录扫描特征)
awk '$9 == 404' /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

4.10 提取所有出现的 IP 地址

1
2
3
4
5
6
7
8
# 从任意日志中提取所有 IPv4 地址
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' /var/log/syslog | sort -u

# 提取并统计出现次数
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' /var/log/syslog | sort | uniq -c | sort -rn | head -20

# 排除内网 IP
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' /var/log/syslog | grep -v -E '^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)' | sort | uniq -c | sort -rn

4.11 SSH 暴力破解 IP 统计

1
2
3
4
5
6
7
8
9
10
11
# 统计 SSH 登录失败的 IP
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20

# 统计使用的用户名
grep "Failed password" /var/log/auth.log | awk '{print $(NF-5)}' | sort | uniq -c | sort -rn | head -20

# 统计成功登录的 IP(确认是否有异常登录)
grep "Accepted" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn

# CentOS / RHEL 系统使用 secure 日志
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20

4.12 按小时统计失败登录

1
2
3
4
5
6
7
8
# 按小时统计 SSH 失败登录(发现暴力破解时间规律)
grep "Failed password" /var/log/auth.log | awk '{print $1, $2, substr($3,1,2)":00"}' | sort | uniq -c | sort -rn

# 按天统计
grep "Failed password" /var/log/auth.log | awk '{print $1, $2}' | sort | uniq -c | sort -rn

# 查找短时间内大量失败的 IP(1 分钟内超过 10 次)
grep "Failed password" /var/log/auth.log | awk '{print $1, $2, substr($3,1,5), $(NF-3)}' | sort | uniq -c | sort -rn | awk '$1 > 10'

4.13 提取 sudo 命令

1
2
3
4
5
6
7
8
# 查看所有 sudo 执行的命令
grep "COMMAND=" /var/log/auth.log | awk -F'COMMAND=' '{print $2}' | sort | uniq -c | sort -rn

# 查看谁执行了 sudo
grep "COMMAND=" /var/log/auth.log | awk '{for(i=1;i<=NF;i++) if($i ~ /USER=/) print $i}' | sort | uniq -c | sort -rn

# 查看 sudo 提权的完整记录
grep -E "(sudo|su\[)" /var/log/auth.log | grep -v "pam_unix"

4.14 时间线生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 将多个日志文件按时间线合并(手工方式)
# 适用于需要关联不同日志源的场景

# 将 syslog 和 auth.log 合并排序
cat /var/log/syslog /var/log/auth.log | sort -k1M -k2n -k3 | less

# 提取特定时间段的所有日志
for log in /var/log/syslog /var/log/auth.log /var/log/kern.log; do
echo "=== $log ==="
awk '$0 >= "Apr 2 10:00" && $0 <= "Apr 2 12:00"' "$log"
done > /tmp/timeline_10to12.txt

# 生成 CSV 格式的时间线
grep -h "" /var/log/syslog /var/log/auth.log | sort -k1M -k2n -k3 | awk '{
timestamp = $1" "$2" "$3
source = $4
$1=$2=$3=$4=""
print timestamp","source","$0
}' > /tmp/timeline.csv

4.15 综合分析命令(额外实用补充)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 统计每个 IP 的请求方法分布
awk '{print $1, $6}' /var/log/nginx/access.log | sed 's/"//g' | sort | uniq -c | sort -rn | head -30

# 查找响应体异常大的请求(可能是数据泄露)
awk '$10 > 1048576 {print $1, $7, $10}' /var/log/nginx/access.log | sort -t' ' -k3 -rn | head -20

# 查找请求耗时异常长的请求(最后一个字段是 request_time)
awk '{if($NF+0 > 10) print $1, $7, $NF}' /var/log/nginx/access.log | sort -t' ' -k3 -rn | head -20

# 统计每秒请求量(发现 DDoS)
awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1-4 | sort | uniq -c | sort -rn | head -10

# 快速查找日志中的 Base64 编码内容(可能是编码的恶意 payload)
grep -oE '[A-Za-z0-9+/]{40,}={0,2}' /var/log/nginx/access.log | sort -u

五、jq 处理 JSON 日志

5.1 jq 简介与安装

越来越多的应用使用 JSON 格式日志(如 Docker、K8s、云服务)

jq 是命令行 JSON 处理器,可以解析、过滤、转换 JSON 数据

1
2
3
4
5
6
# 安装
sudo apt install jq -y # Ubuntu/Debian
sudo yum install jq -y # CentOS/RHEL

# 验证
echo '{"name":"test"}' | jq .

5.2 基本用法

1
2
3
4
5
6
7
8
9
10
11
# 格式化 JSON(美化输出)
cat app.log.json | jq .

# 提取特定字段
cat app.log.json | jq '.timestamp, .message'

# 提取嵌套字段
cat app.log.json | jq '.request.headers."User-Agent"'

# 处理 JSON Lines 格式(每行一个 JSON 对象)
cat app.log.jsonl | jq -r '.remote_addr'

5.3 应急分析场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Docker 容器日志分析
docker logs <container_id> 2>&1 | jq -r 'select(.level == "error") | .message'

# 按字段过滤
cat app.log.jsonl | jq -r 'select(.status_code >= 400) | [.timestamp, .remote_addr, .request_uri, .status_code] | @csv'

# 统计 JSON 日志中的 IP(配合 sort/uniq)
cat app.log.jsonl | jq -r '.remote_addr' | sort | uniq -c | sort -rn | head -20

# 提取特定时间范围的日志
cat app.log.jsonl | jq -r 'select(.timestamp >= "2026-04-01T10:00:00" and .timestamp <= "2026-04-01T12:00:00")'

# 将 JSON 日志转为 CSV 格式(便于 Excel 分析)
cat app.log.jsonl | jq -r '[.timestamp, .remote_addr, .method, .request_uri, .status_code, .body_bytes_sent] | @csv' > /tmp/access.csv

# 查找包含特定关键词的日志条目
cat app.log.jsonl | jq 'select(.message | test("error|fail|denied"; "i"))'

# CloudTrail 日志分析(AWS)
cat cloudtrail.json | jq '.Records[] | select(.eventName == "ConsoleLogin") | {user: .userIdentity.userName, time: .eventTime, ip: .sourceIPAddress}'

# Kubernetes audit 日志分析
cat audit.log | jq 'select(.verb == "delete") | {user: .user.username, resource: .objectRef.resource, name: .objectRef.name, time: .requestReceivedTimestamp}'

5.4 jq 与其他工具的组合

1
2
3
4
5
# jq + GoAccess:将 JSON 日志转为 COMBINED 格式后用 GoAccess 分析
cat app.log.jsonl | jq -r '"\(.remote_addr) - \(.remote_user // "-") [\(.timestamp)] \"\(.method) \(.request_uri) HTTP/1.1\" \(.status_code) \(.body_bytes_sent) \"\(.http_referer // "-")\" \"\(.http_user_agent // "-")\""' | goaccess --log-format=COMBINED -o /tmp/report.html -

# jq + sort/uniq:统计分析
cat app.log.jsonl | jq -r '.request_uri' | sort | uniq -c | sort -rn | head -20

六、实战演练:分析包含攻击痕迹的 access.log

6.1 场景描述

你收到安全告警:某 Web 服务器疑似被入侵

需要分析 Nginx access.log 找到攻击者的行为轨迹

目标:确定攻击 IP、攻击手法、是否成功、影响范围

6.2 分析流程

Step 1:总体概览

1
2
3
4
5
6
7
# 先看日志的时间范围和总量
echo "总行数: $(wc -l < access.log)"
echo "起始时间: $(head -1 access.log | awk '{print $4}')"
echo "结束时间: $(tail -1 access.log | awk '{print $4}')"

# 用 GoAccess 快速生成概览报告
goaccess access.log --log-format=COMBINED -o /tmp/overview.html

Step 2:识别异常 IP

1
2
3
4
5
6
7
8
9
10
# IP 访问量 Top 20
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20

# 对比正常时段,找出异常高频 IP
# 查看这些 IP 的 404 比例(扫描特征)
for ip in $(awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 | awk '{print $2}'); do
total=$(grep -c "^$ip " access.log)
err404=$(grep "^$ip " access.log | awk '$9==404' | wc -l)
echo "$ip total=$total 404=$err404 ratio=$(echo "scale=2; $err404*100/$total" | bc)%"
done

Step 3:分析攻击者行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 假设锁定嫌疑 IP 为 203.0.113.50
ATTACKER="203.0.113.50"

# 查看攻击者的所有请求
grep "^$ATTACKER " access.log > /tmp/attacker.log

# 生成攻击者专属报告
goaccess /tmp/attacker.log --log-format=COMBINED -o /tmp/attacker_report.html

# 按时间排列查看攻击者行为轨迹
grep "^$ATTACKER " access.log | awk '{print $4, $6, $7, $9}' | sed 's/\[//g'

# 检查是否有扫描行为
grep "^$ATTACKER " access.log | awk '{print $9}' | sort | uniq -c | sort -rn

# 检查是否有 SQL 注入尝试
grep "^$ATTACKER " access.log | grep -iE "(union|select|sleep|benchmark|concat)"

# 检查是否有 Webshell 上传/访问
grep "^$ATTACKER " access.log | grep -iE "(upload|shell|\.php\?cmd|\.php\?c=)"

Step 4:判断攻击是否成功

1
2
3
4
5
6
7
8
# 查看攻击者获得 200 OK 的请求(可能成功)
grep "^$ATTACKER " access.log | awk '$9 == 200 {print $7}' | sort -u

# 查看攻击者获得 302 重定向的请求(可能登录成功)
grep "^$ATTACKER " access.log | awk '$9 == 302 {print $7}'

# 查看攻击者请求的响应大小异常(可能获取了数据)
grep "^$ATTACKER " access.log | awk '$10 > 10000 {print $7, $10}' | sort -t' ' -k2 -rn

Step 5:生成分析报告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 汇总输出
echo "========== 应急分析报告 ==========" > /tmp/ir_report.txt
echo "分析时间: $(date)" >> /tmp/ir_report.txt
echo "日志文件: access.log" >> /tmp/ir_report.txt
echo "日志时间范围: $(head -1 access.log | awk '{print $4}') - $(tail -1 access.log | awk '{print $4}')" >> /tmp/ir_report.txt
echo "" >> /tmp/ir_report.txt
echo "=== 可疑 IP ===" >> /tmp/ir_report.txt
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 >> /tmp/ir_report.txt
echo "" >> /tmp/ir_report.txt
echo "=== 攻击类型 ===" >> /tmp/ir_report.txt
echo "SQL 注入尝试: $(grep -ciE '(union.*select|sleep\(|benchmark)' access.log)" >> /tmp/ir_report.txt
echo "目录遍历尝试: $(grep -cE '\.\.\/' access.log)" >> /tmp/ir_report.txt
echo "Webshell 访问: $(grep -ciE '(cmd=|shell=|eval\()' access.log)" >> /tmp/ir_report.txt
echo "" >> /tmp/ir_report.txt
cat /tmp/ir_report.txt

6.3 工具选择建议

场景 推荐工具 原因
快速概览 GoAccess 一条命令出报告
交互式浏览 lnav 支持搜索、过滤、SQL
精确提取 awk/grep/sed 灵活组合,精确控制
JSON 日志 jq JSON 原生支持
大规模集中分析 ELK Stack 多源日志关联
团队协作 ELK + Kibana 可视化分享

6.4 注意事项

分析前先备份原始日志,避免误操作

检查日志是否完整(是否被攻击者清除过)

对比 access.log 和 error.log,error.log 中可能有更多细节

注意时区问题,确保日志时间和系统时间一致

如果攻击者使用了大量 IP(如代理池),单纯按 IP 统计可能不够,需结合 User-Agent 和行为模式分析

参考与延伸

工具官方文档

GoAccess:https://goaccess.io/

lnav:https://lnav.org/

jq:https://stedolan.github.io/jq/

下一步:掌握日志分析工具后,继续学习 29-取证工具 中的数字取证技术


上一章 目录 下一章
27-反弹Shell技术与检测 Linux应急响应 28.5-冷门持久化技术补充