君衍.
本文目的: 研究可视化日志方便进行分析及审计,例如对Nginx的访问日志、雷池WAF的访问日志等等。在使用开源goaccess来进行安装配置分析,便于对WAF未拦截的无攻击特征爬虫等攻击方式的审计。
本文会介绍雷池WAF的访问日志开启方法,及goaccess的安装配置,使用控制台或者HTML查看可视化后的日志,Nginx使用awk等命令的日志分析,以上内容。懂得goaccess的功能,可跳过直接看安装配置。
一、项目环境介绍
首先,对于环境的测试以及模拟安装,我这边在虚拟机环境下部署了Nginx以及雷池WAF来进行测试一些配置,这样一来,如果配置出现问题,那么我们可以使用快照很快捷的还原虚拟机的配置。
可以看到,这里是VMware,本地化部署了一台CentOS虚拟机,同时,这里版本与我在腾讯云上部署的镜像都是CentOS7.6版本的镜像。所以这里可以保证配置的一致性,之后我们对于配置的不同以及流程都是非常清楚的。
我这里已经在CentOS部署了goaccess,所以之后我将在腾讯云服务器上进行部署,下面我们进行查看goaccess的功能,之后介绍goaccess的使用方式。
可以看到这里已经安装了goaccess1.9.3版本,也就是目前的最新版。可以对一些Web日志使用正则进行匹配然后输出,两种输出方式,控制台输出以及HTML界面输出。
二、Goaccess
1、Goaccess介绍
GoAccess - 可视化 Web 日志分析工具。
GoAccess 是一款开源(MIT许可证)的且具有交互视图界面的实时 Web 日志分析工具,通过你的 Web 浏览器或者 *nix 系统下的终端程序即可访问。
能为系统管理员提供快速且有价值的 HTTP 统计,并以在线可视化服务器的方式呈现。 GoAccess 解析指定的 Web 日志文件并将统计结果输出到 X 终端。功能如下:
- 通用统计: 此面板展示了几个主要指标,比如:有效和无效请求的数量,分析这些数据所花费的时间,独立访客的情况,请求的文件,静态文件(CSS, ICO, JPG 等)的完整URL,404错误,被解析的日志文件的大小以及消耗的带宽。
- 独立访客: 此面板按照日期展示了访问次数,独立访客数,以及累计消耗的带宽等指标。具有相同IP,相同访问时间,相同的 UserAgent 的 HTTP 请求将会被识别为独立访客。默认情况下包含了网络爬虫。
您也可以选择使用 --date-spec=hr 参数将按照日期分析修改为按照小时,例如:05/Jun/2016:16 。这对于希望在小时级别去跟踪每日流量非常有帮助。 - 请求的文件: 此面板展示您服务器上被请求次数最多的文件。包含访问次数,独立访客数,百分比,累计消耗带宽,使用的协议,请求方式。
- 请求的静态文件: 列出请求频率最高的静态文件类型,例如:
JPG
,CSS
,SWF
,JS
,GIF
, 和PNG
, 以及和上一个面板一样的其他指标。 另外静态文件可以被添加到配置文件中。 - 404 或者文件未找到: 展示内容与之前的面板类似,但是其数据包含了所有未找到的页面,以及俗称的 404 状态码。
- 主机: 此面板展示主机自身的详细信息。能够很好的发现不怀好意的爬虫以及识别出是谁吃掉了你的带宽。
扩展面板将向您展示更多信息,比如主机的反向DNS解析结果,主机所在国家和城市。如果开启了 参数,选择想查看的 IP 地址并按回车,将会显示 UserAgent 列表。 - 操作系统: 此面板将显示主机使用的操作系统的信息。GoAccess 将尽可能尝试为每一款操作系统提供详细的信息。
- 浏览器: 此面板将显示来访主机使用的浏览器信息。GoAccess 将尽可能尝试为每一款浏览器提供详细的信息。
- 访问次数: 此面板按小时报告。因此将显示24个数据点,每一个均对应每一天的某一个小时。
使用 --hour-spec=min 参数可以设定为按每十分钟报告,并将以 16:4 的格式显示时间。这对发现服务器的峰值访问时段很有帮助。 - 虚拟主机: 此面板将显示从访问日志中解析出来的不同的虚拟主机的情况。此面板仅在日志格式中启用了 %v 参数时显示。
- 来路URL: 如果问题主机通过其他的资源访问了你的站点,以及通过从其他主机上的链接或者跳转到你的站点,则这些来路URL将会被显示在此面板。可以在配置文件中通过
--ignore-panel
开启此功能。(默认关闭) - 来路站点: 此面板将仅显示主机的部分,而不是完整的URL。
- 关键字: 报告支持用在谷歌搜索,谷歌缓存,谷歌翻译上使用关键字。目前仅支持通过 HTTP 使用谷歌搜索。 可以在配置文件中通过
--ignore-panel
开启此功能。(默认关闭) - 地理位置: 根据 IP 地址判断地理位置。统计数据按照大洲和国家分组。需要地理位置模块的支持。
- HTTP 状态码: 以数字表示的 HTTP 请求的状态编码。
- 远程用户(HTTP验证) 通过 HTTP 验证来确定访问文档的权限。如果文档没有被密码保护起来,这部分将会显示为 “-”。此面板默认为开启,除非在日志格式变量中设置了参数
%e
。
2、存储方式
GoAccess 支持三种类型的存储方式。请根据你的需要和系统环境进行选择。
- 默认哈希表
内存哈希表可以提供较好的性能,缺点是数据集的大小受限于物理内存的大小。GoAccess 默认使用内存哈希表。如果你的内存可以装下你的数据集,那么这种模式的表现非常棒。此模式具有非常好的内存利用率和性能表现。
- Tokyo Cabinet 磁盘 B+ 树
使用这种模式来处理巨大的数据集,大到不可能在内存中完成任务。当数据提交到磁盘以后,B+树数据库比任何一种哈希数据库都要慢。但是,使用 SSD 可以极大的提高性能。往后您可能需要快速载入保存的数据,那么这种方式就可以被使用。
- Tokyo Cabinet 内存哈希表
作为默认哈希表的替换方案。因为使用通用类型在内存表现以及速度方面都很平均。
3、配置选项
GoAccess 拥有多个配置选项。获取完整的最新配置选项列表,请运行:./configure --help
-
--enable-debug
使用调试标志编译且关闭编译器优化。
-
--enable-utf8
宽字符支持。依赖 Ncursesw 模块。
-
--enable-geoip=<legacy|mmdb>
地理位置支持。依赖 MaxMind GeoIP 模块。
legacy
将使用原始 GeoIP 数据库。mmdb
将使用增强版 GeoIP2 数据库。 -
--enable-tcb=<memhash|btree>
Tokyo Cabinet 存储支持。
memhash
将使用 Tokyo Cabinet 的内存哈希数据库。btree
将使用 Tokyo Cabinet 的磁盘 B+Tree 数据库。 -
--disable-zlib
禁止在 B+Tree 数据库上使用 zlib 压缩。
-
--disable-bzip
禁止在 B+Tree 数据库上使用 bzip2 压缩。
-
--with-getline
使用动态扩展行缓冲区用来解析完整的行请求,否则将使用固定大小(4096)的缓冲区。
-
--with-openssl
使 GoAccess 与其 WebSocket 服务器之间的通信能够支持 OpenSSL。
4、自定义日志/日期格式
GoAccess 可以解析虚拟的任意 Web 日志格式。
预定义的选项包括: 通用日志格式,联合日志格式,包含虚拟主机,W3C 格式以及亚马逊 CloudFront(分布式下载)。
GoAccess 允许任意的自定义格式字符串。有两种方法配置日志格式。最简单的方式是运行 GoAccess 时使用 -c
显示一个配置窗口。但是这种方式不是永久有效的,因此你需要在配置文件中设定格式。
配置文件位于:%sysconfdir%/goaccess.conf
或者 ~/.goaccessrc
注意: %sysconfdir%
可能是 /etc/
, /usr/etc/
或者 /usr/local/etc/
-
–time-format
参数 time-format 后跟随一个空格符,指定日志的时间格式,包含普通字符与特殊格式说明符的任意组合。他们都由百分号 (%)开始。参考
man strftime
。 %T 或者 %H:%M:%S. -
–date-format
参数 date-format 后跟随一个空格符,指定日志的日期格式,包含普通字符与特殊格式说明符的任意组合。他们都由百分号 (%)开始。参考
man strftime
。 -
–log-format
参数 log-format 后跟随一个空格符或者制表分隔符(
\t
),用于指定日志字符串格式。
另外可以指定原始 日志/日期/时间 格式,简单来说,下表中的预定义日志格式名称可以用作 日志/日期/时间 格式的变量。GoAccess 可以处理在一个变量中处理一个预定义名称,而在另一变量中处理另外一个预定义名称。
COMBINED | 联合日志格式
VCOMBINED | 支持虚拟主机的联合日志格式
COMMON | 通用日志格式
VCOMMON | 支持虚拟主机的通用日志格式
W3C | W3C 扩展日志格式
SQUID | Native Squid 日志格式
CLOUDFRONT | 亚马逊 CloudFront Web 分布式系统
CLOUDSTORAGE | 谷歌云存储
AWSELB | 亚马逊弹性负载均衡
AWSS3 | 亚马逊简单存储服务 (S3)
注意: 一般来说,需要在包含空格、逗号、管道符、引号、/、括号的值的周围引用引号。内部引号必须进行转义处理。
注意: 使用管道传送数据给 GoAccess 时不会提示 日志/日期/时间 配置对话框,你需要在配置文件或者命令行中提前定义。
5、特殊格式说明符
%x
匹配 time-format 和 date-format 变量的日期和时间字段。用于使用时间戳来代替日期和时间两个独立变量的场景。%t
匹配 time-format 变量的时间字段。%d
匹配 date-format 变量的日期字段。%v
根据 canonical 名称设定的服务器名称(服务区或者虚拟主机)。%e
请求文档时由 HTTP 验证决定的用户 ID。%h
主机(客户端IP地址,IPv4 或者 IPv6)。%r
客户端请求的行数。这些请求使用分隔符(单引号,双引号)引用的部分可以被解析。否则,需要使用由特殊格式说明符(例如:%m,%U,%q和%H)组合格式去解析独立的字段。- 注意: 既可以使用
%r
获取完整的请求,也可以使用%m
,%U
,%q
and%H
去组合你的请求,但是不能同时使用。
- 注意: 既可以使用
%m
请求的方法。%U
请求的 URL。- 注意: 如果查询字符串在
%U
中,则无需使用%q
。但是,如果 URL 路径中没有包含任何查询字符串,则你可以使用%q
查询字符串将附加在请求后面。
- 注意: 如果查询字符串在
%q
查询字符串。%H
请求协议。%s
服务器回传客户端的状态码。%b
回传客户端的对象的大小。%R
HTTP 请求的 “Referer” 值。%u
HTTP 请求的 “UserAgent” 值。%D
处理请求的时间消耗,使用微秒计算。%T
处理请求的时间消耗,使用带秒和毫秒计算。%L
处理请求的时间消耗,使用十进制数表示的毫秒计算。%^
忽略此字段。%~
继续解析日志字符串直到找到一个非空字符(!isspace)。~h
在 X-Forwarded-For (XFF) 字段中的主机(客户端 IP 地址,IPv4 或者 IPv6)。
三、雷池访问日志
首先,雷池是默认没有开启访问雷池监听的80端口的日志的,这里需要自己进行配置。同时,我们配置之后,与Apache或者Nginx的日志可以进行对比,我这里除了博客记录的配置,再没有做过多配置。所以Nginx的日志在配置了雷池之后,将8080端口只设置为了本机可以访问,剩余的80端口经过雷池WAF的检测然后转发过来,所以可以看到Nginx的日志的源IP地址所有都是本机的IP地址。
所以我们这种配置对于攻击IP的获取,比如一些多元低频的扫描攻击,不断去变换IP地址,配合脚本对整站进行扫描,这种雷池拦截率还是有点困难的,限频是肯定不行的。我们通过Nginx的access.log日志只可以看到这里有人进行了扫描,却不知道哪几个IP地址。如果我们将这几个扫描的网段封禁了,那么还是可以在一定情况下防护了源站。这里由于我是雷池WAF社区版,不是别的安全产品,对于浏览器的指纹等等这种方式对攻击进行分析判断是不是在扫描这种方式在我目前的环境下是做不到的。
所以,这里我对于这种多源低频类的攻击只能进行IP的封禁,需要进行配置雷池WAF的访问日志结合访问,从而也可观察是哪些payload完成了绕过以及其响应包是否完成了攻击以及封禁这种多源低频的攻击IP。
1、配置文件改变
雷池WAF的Nginx主配置文件默认路径在/data/safeline/resources/nginx/nginx.conf
这里我们需要在该文件中进行配置,从而使雷池记录访问的日志。
修改前:
修改后:
这里我们将访问日志记录开启,同时,日志将被记录在/var/log/nginx/access.log
该目录下。
2、docker配置
- 1、首先检查该配置文件是否正确:
docker exec safeline-tengine nginx -t
- 2、重新加载nginx:
docker exec safeline-tengine nginx -s reload
如上图配置即为正确。
3、示例测试
首先,我们进入到该目录下:
[root@zhongyan nginx]# cd /data/safeline/logs/nginx/
[root@zhongyan nginx]# ll
total 24
-rw-r--r--. 1 root root 16494 Jul 5 23:25 access.log
-rw-r--r--. 1 root root 908 Jul 5 22:20 error.log
[root@zhongyan nginx]# vim access.log
这里可以看到,我的访问源IP地址所有都是来自于主机,这里我虚拟机的网络模式强调下,我的是NAT模式的,
这里我们可以看到,该VMnet8是217网段下的。
所以,我们这里配置之后,记录的日志都是正确的。以及腾讯云下的雷池WAF访问日志:
可以看到这里有几个IP地址依旧在变换IP扫描,之后我们在雷池WAF控制台通用配置里面添加IP组,将其汇总到一块,然后在自定义规则中创建规则进行匹配,完成拦截。
四、Goaccess安装
1、安装依赖
我们需要下载依赖libmaxminddb:github下载地址
点击即可完成下载。
接着上传至/usr/local/etc
目录下,解压编译完成安装。
[root@VM-8-11-centos etc]# ll
total 1520
drwxr-xr-x 7 lighthouse 984 4096 Jul 6 10:46 goaccess
-rw-r--r-- 1 root root 821878 Jul 6 10:39 goaccess-1.9.3.tar.gz
-rw-r--r-- 1 root root 727713 Jul 6 10:55 libmaxminddb-1.10.0.tar.gz
[root@VM-8-11-centos etc]# tar -xvzf libmaxminddb-1.10.0.tar.gz
[root@VM-8-11-centos etc]# mv libmaxminddb-1.10.0 libmaxminddb
[root@VM-8-11-centos etc]# ll
total 1524
drwxr-xr-x 7 lighthouse 984 4096 Jul 6 10:46 goaccess
-rw-r--r-- 1 root root 821878 Jul 6 10:39 goaccess-1.9.3.tar.gz
drwxr-xr-x 8 lighthouse lighthouse 4096 Jun 11 01:18 libmaxminddb
-rw-r--r-- 1 root root 727713 Jul 6 10:55 libmaxminddb-1.10.0.tar.gz
[root@VM-8-11-centos etc]# cd libmaxminddb/
[root@VM-8-11-centos libmaxminddb]# ./configure
[root@VM-8-11-centos libmaxminddb]# make
[root@VM-8-11-centos libmaxminddb]# make install
即可完成编译安装libmaxminddb。
之后由于我们编译安装需要用到--enable-utf8
,所以,我们还需要安装一个依赖:ncurses
yum -y install ncurses-devel
即可安装完成。
2、编译安装
- 1、这里我们需要从官网下载源码包:goaccess1.9.3源码包
需要等待几秒,即可下载完毕,文件大小在800多kb。
- 2、接着文件上传至腾讯云服务器
/usr/local/etc
目录下,进行解压。
[root@VM-8-11-centos ~]# cd /usr/local/etc/
[root@VM-8-11-centos etc]# ll
total 804
-rw-r--r-- 1 root root 821878 Jul 6 10:39 goaccess-1.9.3.tar.gz
[root@VM-8-11-centos etc]# tar -xzvf goaccess-1.9.3.tar.gz
- 3、改名,预编译:
[root@VM-8-11-centos etc]# ll
total 808
drwxr-xr-x 7 lighthouse 984 4096 Jun 1 08:40 goaccess-1.9.3
-rw-r--r-- 1 root root 821878 Jul 6 10:39 goaccess-1.9.3.tar.gz
[root@VM-8-11-centos etc]# mv goaccess-1.9.3 goaccess
[root@VM-8-11-centos etc]# ll
total 808
drwxr-xr-x 7 lighthouse 984 4096 Jun 1 08:40 goaccess
-rw-r--r-- 1 root root 821878 Jul 6 10:39 goaccess-1.9.3.tar.gz
[root@VM-8-11-centos etc]# cd goaccess/
[root@VM-8-11-centos goaccess]# ./configure --enable-utf8 --enable-geoip=mmdb
[root@VM-8-11-centos goaccess]# make
[root@VM-8-11-centos goaccess]# make install
以上即可安装完成goaccess。
五、Goaccess对Nginx日志分析
1、常用命令参数
查看命令参数:
goaccess -h
常用命令参数:
-a --agent-list 启用由主机用户代理的列表。为了更快的解析,不启用该项。
-d --with-output-resolver 在 HTML/JSON 输出中开启 IP 解析,会使用 GeoIP 来进行 IP 解析。
-f --log-file 需要分析的日志文件路径。
-p --config-file 配置文件路径。
-o --output 输出格式,支持。html、json、csv。
-m --with-mouse 控制面板支持鼠标点击。
-q --no-query-string 忽略请求的参数部分。
--real-time-html 实时生成 HTML 报告。
--daemonize 守护进程模式,--real-time-html 时使用。
常用匹配规则:
%t 匹配 time-format 格式的时间字段
%d 匹配 date-format 格式的日期字段
%h host(客户端 ip 地址,包括 ipv4 和 ipv6)
%r 来自客户端的请求行
%m 请求的方法
%U URL 路径
%H 请求协议
%s 服务器响应的状态码
%b 服务器返回的内容大小
%R HTTP 请求头的 referer字段
%u 用户代理的 HTTP 请求报头
%D 请求所花费的时间,单位微秒
%T 请求所花费的时间,单位秒
%^ 忽略这一字段
2、终端模式运行
控制台操作方式:
F1 主帮助页面
F5 重绘主窗口
q 退出
1-15 跳转到对应编号的模块位置
o 打开当前模块的详细视图
j 当前模块向下滚动
k 当前模块向上滚动
s 对模块排序
/ 在所有模块中搜索匹配
n 查找下一个出现的位置
g 移动到第一个模块顶部
G 移动到最后一个模块底部
命令如下:
goaccess -a -d -f /usr/local/nginx/logs/access.log -p /usr/local/etc/goaccess/goaccess.conf
-a --agent-list 启用由主机用户代理的列表。为了更快的解析,不启用该项。
-d --with-output-resolver 在 HTML/JSON 输出中开启 IP 解析,会使用 GeoIP 来进行 IP 解析。
-f --log-file 需要分析的日志文件路径。
-p --config-file 配置文件路径。
点击空格完成选择,要求配置 access.log 的时间和日志格式。 Nginx 默认的日志格式就是 NCSA,所以我们选择第一个,回车即可。
GoAccess 分析日志完成后会在终端上显示分析结果:
这里我们也可以让其使用中文显示:
LANG="zh_CN.UTF-8" bash -c "goaccess /usr/local/nginx/logs/access.log"
3、HTML模式运行
一般情况下,Goaccess运行在控制台下的,但是为了更方便的分析日志结果,我们也可以通过Goaccess的HTML模式将分析结果转换为HTML,通过浏览器也可以进行访问。这里我们需要配置Goaccess主配置文件。
默认NCSA配置:
time-format %H:%M:%S
date-format %d/%b/%Y
log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u"
在goaccess配置文件末尾中添加以上几行即可。
这样我们设置了goaccess匹配的格式,从而在HTML匹配过程中使用以上匹配标准。接着我们使用HTML匹配命令:
goaccess -a -d -f access.log -p /usr/local/goaccess/etc/goaccess/goaccess.conf -o /xss/logs/goaccess.html
这里我们-f后面加上需要进行匹配分析的日志,-p加上之前我们更改后的主配置文件路径,同时,-o后面加上我们生成的HTML路径。这里路径我放在了已经可以访问的路径下。
下面我们直接访问该路径即可。
可以看到如上日志分析后的HTML,当然,我们也可以设置中文输出:
LANG="zh_CN.UTF-8" bash -c "goaccess -p /usr/local/goaccess/etc/goaccess/goaccess.conf /usr/local/nginx/logs/access.log -o /xss/logs/go.html"
紧接着我们访问即可:
六、Goaccess对雷池日志分析
1、控制台模式
首先我们需要知道设置后的雷池WAF访问日志的路径,这里可以在雷池WAF的nginx主配置文件中进行查看。
我的雷池WAF存储位置在:
找到路径之后我们需要进行查看其与Nginx的日志字段不同之处,从而使Goaccess能够根据字符匹配完整准确。
这里我们需要明白雷池WAF与Nginx每个字段的含义,同时两者有什么不同,经过我的分析,我发现雷池WAF的日志比Nginx多一个字段,那就是请求的主机名,下面我分别说明下雷池WAF日志每个字段的含义。
192.168.217.1 - - [04/Jul/2024:15:16:39 +0800] "192.168.217.162" "GET / HTTP/1.1" 200 800 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" "-"
请求来源IP-客户身份信息-远程用户名-请求时间戳-请求主机名-请求行包括方式、路径、版本-状态码-响应大小-refer-UA字段-其他信息
所以,对比匹配规则,这个请求多一个请求主机名,这里我采取的操作是进行了忽略。
%t 匹配 time-format 格式的时间字段
%d 匹配 date-format 格式的日期字段
%h host(客户端 ip 地址,包括 ipv4 和 ipv6)
%r 来自客户端的请求行
%m 请求的方法
%U URL 路径
%H 请求协议
%s 服务器响应的状态码
%b 服务器返回的内容大小
%R HTTP 请求头的 referer字段
%u 用户代理的 HTTP 请求报头
%D 请求所花费的时间,单位微秒
%T 请求所花费的时间,单位秒
%^ 忽略这一字段
那么,对于雷池WAF的匹配规则将变为:
time-format %H:%M:%S
date-format %d/%b/%Y
log-format %h %^[%d:%t %^] %^ "%r" %s %b "%R" "%u"
下面我们在控制台对雷池WAF日志进行匹配分析(这里没有加-p配置文件,那么需要自己去设置):
LANG="zh_CN.UTF-8" bash -c "goaccess /data/safeline/logs/nginx/access.log"
更改前:
空格选择之后,按c键,对日志格式匹配规则进行更改;
更改后:
加上一个字段的匹配之后,回车:
可以看到这里已经匹配输出完毕。
2、HTML模式分析
同样的,我们修改配置文件:goaccess.conf
time-format %H:%M:%S
date-format %d/%b/%Y
log-format %h %^[%d:%t %^] %^ "%r" %s %b "%R" "%u"
尾部加上匹配规则并保存。
即可访问成功看到匹配分析之后的日志。当然,对于别的日志我们需要对字段的匹配进行改变,从而匹配到日志的各个字段完成对日志的分析。