GoAccess:轻量、高效的Nginx日志分析器

前情提要

最近,我发现博客经常出现莫名其妙的日志,诸如 /wp/login.php 之类的日志更是常见。

但问题是我的博客是 Hexo 类的博客,整个服务器上就装了个 Nginx,并没有 PHP,所以对我的博客基本上没有影响。

但老话说得好啊:癞蛤蟆趴人腿上,不咬人但膈应人。搞这种攻击的就是这么个情况。于是,我就得考虑下把这些攻击屏蔽掉了。

我一开始想要实现的是拦截所有海外IP,因为我的博客做了境内与海外的分流,一般来说海外来源并不需要这台服务器提供服务。但我所购买的服务器提供商中国电信天翼云似乎并没有提供这类功能,通过给他们提交工单咨询,得知可以通过 ACL 或者安全组来拦截部分攻击的 IP,于是就想要部署下。

但 Nginx 日志对于我来说,虽然能读,但能读的不多。于是我就想要一个用来分析 Nginx 日志的工具(PHP 的 だめよ

介绍一下 GoAccess

正巧,看到了这篇文章:GoAccess:轻量级nginx日志分析工具 | 血衫非弧の一存

文章中提到的 GoAccess 这个工具,完美的符合了我的需求:不需要引入 PHP,轻量,纯静态。

一个 HTML,解决了困扰我好长一段时间的难题。

顺带一提,是可以看到访客访问了什么内容的,所以建议不要乱访问一些奇奇怪怪的文件了嗷,会被记录下来的

当我从面板上看到某 IP 访问这些不存在的内容,且次数过多之后,就会直接在 CDN 访问控制、云服务器安全组上直接禁掉,直接就是封掉一个 B 段

遇到的问题、踩过的坑

介绍了这么多,也该提一嘴遇到的一些问题了。首先就是在安装时,默认源可能是不包含 GoAccess 的,因此需要引入一下安装源。这里以我常用的 Debian 为例,Ubuntu 也可以参考一下

引入源并安装

1
2
3
4
wget -O - https://deb.goaccess.io/gnugpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
sudo apt-get update
sudo apt-get install goaccess

在安装之后按照官方的文档,可以生成一个 HTML 文件看看效果

1
goaccess access.log -a -o report.html

access.log 是 Nginx 的日志文件,report.html 则是输出的 HTML 文件,可以根据需要调整下

但是如果日志比较大,而服务器带宽又比较小的情况下,加载可能比较慢。如果以 Nginx 来传输,推荐开启 Gzip 或者 Brotli 来压缩以减少传输的数据,至于如何开启,就是另一篇文章了(笑)

增量更新

作为一个日志分析工具,所统计的数据自然是越多越好,因为数据越多,越能看出趋势。什么叫带数据啊(战术后仰

搜索了不少文章,也愣是没找到。正当我以为 GoAccess 没有这个功能的时候,用我那可怜的英语能力看了一眼官方文档,才发现有这个:

那句话怎么说来着?

众里寻他千百度,蓦然回首,那人却在,灯火阑珊处。

——辛弃疾青玉案·元夕

用法也就很明显了,同样是上面的示例代码,没有建立过数据库时,这样用:

1
2
mkdir db
goaccess access.log -a -o report.html --db-path=./db/ --persist

之后更新数据时,就这样写

1
goaccess access.log -a -o report.html --db-path=./db/  --restore --persist

虽然不知道官方是不是这样写的,但是我的习惯就是数据增量先导入,再导出,以免覆盖原来的数据,导致数据火葬场

无法实时更新

GoAccess 其实是支持实时更新的,但我之前启用这个功能的时候一直都无法实时更新,其实问题的原因是无法通过 WebSocket 连接到服务器。因为我为了减小传输的数据,启用了 Brotli 压缩,而 Brotli 只有在启用 HTTPS 的情况下才会包含在浏览器的请求头中,否则浏览器就不会请求 Brotli 压缩,也就跟没启用一样。

启用了 HTTPS,且同样启用了 HTTP2

未启用 HTTPS

问题也就出于此处。因为启用了 HTTPS,导致 WebSocket 的连接也升级为了 SSL 加密的,即 wss:// 。我又不想要关闭 Brotli 压缩,自然也不能关闭 HTTPS,因此只有两个选择可选了:

  • 开启 GoAccess 的 WebSocket 加密

  • 使用 Nginx 来反代 GoAccess 的 WebSocket

为了安全性,我的建议是反代 GoAccess 的 WebSocket。服务器桑,你也不想被平白无故的突然被开一个口子吧

因此,直接修改网站的配置文件,例如 goaccess.conf 2

1
2
3
4
5
6
7
8
9
10
11
12
location /wss {
proxy_pass http://127.0.0.1:7890;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 600s; # 设置 WebSocket 的超时时间,这里设置的 600 秒

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

connection_upgrade 变量报错9

在修改完了网站配置文件之后,执行 nginx -t 时,报了个错:

1
2
nginx: [emerg] unknown "connection_upgrade" variable
nginx: configuration file /etc/nginx/nginx.conf test failed

这个错误在引用资源9里得到了解决。引用一下文章作者的一段话:

我大概可以猜出来map 代码段该作用主要是根据客户端请求中 $http_upgrade 的值,来构造改变 $connection_upgrade 的值,即根据变量 $http_upgrade 的值创建新的变量 $connection_upgrade。
由于我没有进行map映射,它不知道connection_upgrade是什么,所以就会出现unknown "connection_upgrade" variable错误。

因此解决办法是修改 Nginx 的配置文件 nginx.conf

http 部分中加入以下内容,推荐加入在 include 之上

1
2
3
4
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

之后便可以正常使用 GoAccess 了。

后记

其实一开始我是不想做任何日志分析的,无他,只是因为个人对于每一位访客隐私权的那份尊重。正如我在博客的关于页面写的那样:

本博客出于加载速度和访客的隐私考虑,不单独设置分析代码。
本博客只会统计必要的数据,数据来源于搜索引擎统计数据和CDN统计数据。所统计的数据包括搜索引擎点击次数、搜索引擎点击关键词、访客来源地区(大概的地区)、响应速度等。不会设置跟踪 Cookies。

但是,总有一些人为了一己私利,便开始了对他人利益的侵蚀。被逼无奈,只能开始了对日志的追踪分析。现在你去看本博客的关于页面,可能上面这段话已经没有了,抑或已经修改,但无论如何它至少存在过,至少也为了尊重每个访客的隐私权而努力过。

写到这里,我最大的感触就是《共产主义宣言》的一段话10

       一个幽灵,共产主义的幽灵,在欧洲游荡。为了对这个幽灵进行神圣的围剿,旧欧洲的一切势力,教皇和沙皇、梅特涅和基佐、法国的激进派和德国的警察,都联合起来了。
       有哪一个反对党不被它的当政的敌人骂为共产党呢?又有哪一个反对党不拿共产主义这个罪名去回敬更进步的反对党人和自己的反动敌人呢?

       从这一事实中可以得出两个结论:

       共产主义已经被欧洲的一切势力公认为一种势力;

       现在是共产党人向全世界公开说明自己的观点、自己的目的、自己的意图并且拿党自己的宣言来反驳关于共产主义幽灵的神话的时候了。

本文撰于 2023 年 5 月 4 日晚,Leao Duan。

引用内容

  1. GoAccess:轻量级nginx日志分析工具 | 血衫非弧の一存

  2. 利用 GoAccess 分析日志,将 Web 访问数据可视化 - 嘻嘻琦琦

  3. GoAccess - Manual Page

  4. GoAccess - 中文站 - 可视化 Web 日志分析工具

  5. GoAccess分析Web日志 - 常见-youmen - 博客园

  6. 日志分析工具 - GoAccess - 玩转Linux - SegmentFault 思否

  7. Nginx 安装 SSL 配置 HTTPS 超详细完整全过程 - 个人文章 - SegmentFault 思否

  8. 如何为 Nginx 启用谷歌 Brotli 高级压缩算法 - 宝塔(BT)重新编译 Nginx - VirCloud’s Blog - Learning&Sharing

  9. nginx: [emerg] unknown “connection_upgrade” variable解决与思考 - 个人文章 - SegmentFault 思否

  10. 《共产党宣言》全文 — 东南大学