我的博客网站有时候会被黑客光顾,短时间有大量的request涌入(1s内有上百上千的并发访问),直接导致CPU爆表,造成网站无法正常访问,于是考虑写一个日志分析工具
实施步骤
主要有三步:
- 通过正则提取访问日志里的关键信息
- 处理提取的数据(将日期处理为javascript可识别的日期格式)。
- 数据渲染到页面,可通过用户界面操作、查看、分析日志数据
编写正则表达式
通过观察发现日志有以下格式:第一部分为IP,然后是两个横杠,紧接着第二部分日期,然后空格分开双引号里是访问路径;每条记录占一行。
我这里准备提取三部分数据:
- 访问源的IP
- 访问日期
- 访问路径
于是编写以下正则:
//多行、全局匹配
const matchAllReg = /^(\d+\.\d+\.\d+\.\d+)\s-\s-\s\[([^\]]+)\]\s"([^"]+)"/mg;
const matchAllResult = logTextContent.matchAll(matchAllReg)
//matchAllResult 是一个包含三个捕获(IP、日期、URL)的迭代器,可通过for...of迭代遍历
接下来就是通过JavaScript提供的FileReader
的readAsText
方法读取日志文件的文本内容,然后根据正则规则进行数据提取.
将日期转换为时间戳
由于日期是12/Nov/2020:21:23:19 +0800
的格式,Js是无法识别的,因此需要进行日期格式的转换,这里我打算将其转换为时间戳类似: 2020-11-12 21:23:19
const enToNumb = {
Jan:"01",
Feb:"02",
Mar:"03",
Apr:"04",
May:"05",
Jun:"06",
Jul:"07",
Aug:"08",
Sep:"09",
Oct:"10",
Nov:"11",
Dec:"12"
}
let nginxDateStr = "12/Nov/2020:21:23:19 +0800"
nginxDateStr = nginxDateStr.slice(0,20);// 12/Nov/2020:21:23:19
const dateFragArr = nginxDateStr.split(":")[0].split("/").reverse();//["2020","Nov","12"]
dateFragArr[1] = enToNumb[dateFragArr[1]];//将月份格式由英文改为数字
const timeFrag = nginxDateStr.split(":").slice(1,4);// 21:23:19
const timeStamp = dateFragArr.join("-") + " " + timeFrag;
数据渲染到页面
梳理了下自己的需求,并进行简单的分析,设计了以下功能点:
- 读取本机的日志文本格式文件
- 提取日志里的三部分数据:IP、访问日期、访问路径(URL)
- 根据过滤条件(IP、访问日期)进行数据的筛选和过滤
- 以IP分组进行数据统计,查看某个IP的访问次数
以上功能可以帮助我筛选某个时间段内服务器的访问量,统计并识别哪些是恶意IP(非正常的高频次访问),在安全控制台将其屏蔽。
最终界面
默认界面
条件过滤(IP、日期)
分组统计
最后附上本工具的线上地址:Nginx日志分析工具