我有一个修改后的日志文件,列出了访问我的服务器的所有 IP 地址。
每行 IP 地址旁边都有一个日期/时间戳。
在过滤机器人和恶意活动的过程中,我想检查是否有任何 IP 地址在 15 秒内发出了超过 5 个请求。
我已经发布了一个问题关于如何从第一个请求开始衡量这一点,但我想进一步讨论。
我目前正在学习(G)AWK,我想了解更多。如果可能的话,我希望在 (G)AWK 中完成并尽可能明确地解释,这样我就可以研究这个脚本,并希望将来我能够自己编写类似的脚本。
虽然我知道这很可能可以用 Python 完成,但我目前还没有学习 Python。
输入样本
这是我的日志文件的完整(工作)修改(以混淆 IP 地址)版本: 日志文件.csv。
并且,下面是该文件的[进一步修改]示例,以防您更愿意测试您的结果:
03/Nov/2020:06:33:09|000.000.000.001|200|/page-1/
03/Nov/2020:07:12:21|000.000.000.002|200|/page-2/
03/Nov/2020:07:24:52|000.000.000.003|200|/page-3/
03/Nov/2020:07:30:50|000.000.000.004|200|/page-4/
03/Nov/2020:07:47:29|000.000.000.005|200|/page-5/
03/Nov/2020:07:52:42|000.000.000.006|200|/page-6/
03/Nov/2020:07:52:55|000.000.000.007|200|/page-7/
03/Nov/2020:08:00:11|000.000.000.008|200|/page-8/
03/Nov/2020:08:05:00|000.000.000.009|200|/page-9/
03/Nov/2020:08:05:06|000.000.000.010|301|/page-10/
03/Nov/2020:08:05:32|000.000.000.007|200|/page-11/
03/Nov/2020:09:02:49|000.000.000.011|304|/page-12/
03/Nov/2020:09:02:49|000.000.000.011|404|/page-13/
03/Nov/2020:09:13:18|000.000.000.011|304|/page-14/
03/Nov/2020:09:13:19|000.000.000.011|404|/page-15/
03/Nov/2020:09:14:20|000.000.000.012|200|/page-16/
03/Nov/2020:09:23:48|000.000.000.011|304|/page-17/
03/Nov/2020:09:23:49|000.000.000.011|404|/page-18/
03/Nov/2020:09:34:19|000.000.000.011|304|/page-19/
03/Nov/2020:09:34:19|000.000.000.011|404|/page-20/
03/Nov/2020:09:35:42|000.000.000.013|301|/page-21/
03/Nov/2020:09:35:42|000.000.000.013|404|/page-22/
03/Nov/2020:09:44:49|000.000.000.011|304|/page-23/
03/Nov/2020:09:44:49|000.000.000.011|404|/page-24/
03/Nov/2020:09:53:38|000.000.000.014|200|/page-25/
03/Nov/2020:09:55:19|000.000.000.011|304|/page-26/
03/Nov/2020:09:55:19|000.000.000.011|404|/page-27/
03/Nov/2020:10:05:49|000.000.000.011|304|/page-28/
03/Nov/2020:10:05:49|000.000.000.011|404|/page-29/
03/Nov/2020:10:06:27|000.000.000.005|200|/page-30/
03/Nov/2020:10:16:19|000.000.000.011|304|/page-31/
03/Nov/2020:10:16:19|000.000.000.011|404|/page-32/
03/Nov/2020:10:17:21|000.000.000.015|200|/page-33/
03/Nov/2020:10:20:35|000.000.000.016|200|/page-34/
03/Nov/2020:10:20:37|000.000.000.017|404|/page-35/
03/Nov/2020:10:20:42|000.000.000.017|404|/page-39/
03/Nov/2020:10:20:49|000.000.000.016|200|/page-40/
03/Nov/2020:10:20:55|000.000.000.017|404|/page-41/
03/Nov/2020:10:21:01|000.000.000.017|404|/page-42/
03/Nov/2020:10:21:03|000.000.000.017|404|/page-43/
03/Nov/2020:10:21:05|000.000.000.017|404|/page-44/
03/Nov/2020:10:21:06|000.000.000.017|404|/page-45/
03/Nov/2020:10:21:11|000.000.000.017|404|/page-46/
03/Nov/2020:10:21:14|000.000.000.016|200|/page-47/
03/Nov/2020:10:21:34|000.000.000.016|200|/page-48/
03/Nov/2020:10:21:47|000.000.000.016|200|/page-49/
03/Nov/2020:10:22:14|000.000.000.016|200|/page-50/
03/Nov/2020:10:22:15|000.000.000.016|200|/page-51/
03/Nov/2020:10:22:15|000.000.000.016|200|/page-52/
03/Nov/2020:10:22:16|000.000.000.016|200|/page-52/
03/Nov/2020:10:22:17|000.000.000.016|200|/page-53/
03/Nov/2020:10:22:18|000.000.000.019|200|/page-1/
03/Nov/2020:10:22:20|000.000.000.016|200|/page-55/
03/Nov/2020:10:22:20|000.000.000.016|200|/page-56/
所需的输出
我希望您生成一份名为 的文档bot-list.txt
,其中包含以下内容的列表在 15 秒内发出 5 个或更多请求的 IP 地址任何时间(不一定是前 5 个)。我可能想稍后调整频率/持续时间。
由于日志文件很大,我认为在这里发布整个日志文件并不合适。然而,上面(修改后的)示例的输出只有 2 个 IP 地址。因此,测试完整的日志文件将更加可靠。
000.000.000.017
000.000.000.016
请明确说明您是如何实现这一结果的。作为额外的好处,如果您确实使用任何晦涩的技术/功能,如果您能指出一个参考资料,我可以在其中了解有关该技术的更多信息,我将很高兴。
所以,要明确的是:
- 搜索每个唯一的IP
log-file.csv
- 如果该 IP 有 5 个或更多实例,请使用每行上的日期/时间戳计算它们之间的秒数差异。
- 隔离在 15 秒内访问 5 个页面(或更多)的 IP 地址。
- 将这些 IP 地址附加到
bot-list.txt
. - 如果可能,请在单个 (G)AWK 脚本中完成该任务。
欢迎就如何改进这一概念提供进一步的建议。
我尝试过的
老实说,我不知道如何比较 GAWK 中的行,但从我上一个问题的一些答案中可以清楚地看出,这是可能的。
目前,我正在阅读《Effective AWKProgramming》一书。这很有趣,但我对其中的一些感到挣扎。我也在研究关联数组,但由于我没有编程背景,所以我正在慢慢学习这些知识。
我找不到任何可以解决我的具体问题的东西,并且有关此主题的视频很少。
如果有人可以指出可以帮助我解决此类问题的有用资源,我将不胜感激。
我尝试比较日期:
egrep "000.111.000.111" log-file.csv | awk 'BEGIN{FS="|"; ORS=" "} NR==1 || NR==5 {print $1,$2}' | sed -e 's/[\/:]/\ /g' -e 's/Jan/1/g' -e 's/Feb/2/g' -e 's/Mar/3/g' -e 's/Apr/4/g' -e 's/May/5/g' -e 's/Jun/6/g' -e 's/Jul/7/g' -e 's/Aug/8/g' -e 's/Sep/9/g' -e 's/Oct/10/g' -e 's/Nov/11/g' -e 's/Dec/12/g' | awk '{print $3,$2,$1,$4,$5,$6 "," $10,$9,$8,$11,$12,$13","$14}' | awk -F, '{d2=mktime($2);d1=mktime($1);print d2-d1, $3}' | awk '{if($1<15)print $2}' >> bot-list.txt
不幸的是,正如您所看到的,我无法在 (G)AWK 中完成所有工作,但如果您可以的话,我将不胜感激。
(这是我第二次使用 Stack Exchange。我尝试遵循有关如何提出问题的建议,如果我犯了任何错误,我很高兴收到进一步的建议)。
谢谢。
答案1
一种简单的强力方法,在转换为纪元秒到内存(数组secs[]
)后读取所有 IP 地址和时间戳,然后读取整个文件后,一次循环遍历数组一个 IP 地址,查看差异每 5 个条目加上时间戳,看看是否有少于 15 秒的条目:
$ cat tst.awk
BEGIN { FS="|" }
{
split($1,t,"[/:]")
monthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",t[2])+2)/3
currSecs = mktime(t[3] " " monthNr " " t[1] " " t[4] " " t[5] " " t[6])
secs[$2][++count[$2]] = currSecs
}
END {
range = 5
for (ip in secs) {
for (beg=1; beg<=(count[ip]-range)+1; beg++) {
end = beg + range - 1
if ( (secs[ip][end] - secs[ip][beg]) < 15 ) {
print ip
break
}
}
}
}
$ awk -f tst.awk file
000.000.000.016
000.000.000.017
这确实意味着您需要有足够的内存来存储 IP 地址和纪元秒的列表,但您的文件必须很大(数十亿行)才会成为问题。
编辑:根据您的问题下的评论,您的输入文件的顺序不正确(递增日期+时间),因此我们可以这样做来解决这个问题:
$ awk -F'|' '
{
split($1,t,"[/:]")
monthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",t[2])+2)/3
currSecs = mktime(t[3] " " monthNr " " t[1] " " t[4] " " t[5] " " t[6])
print currSecs, NR, $0
}
' log-file.csv | sort -k1,1n -k2,2n | cut -d' ' -f3- > sorted-log-file.csv
然后在 THAT 上运行上述脚本以获得以下 50 个 IP 地址输出:
$ awk -f tst.awk sorted-log-file.csv | sort
000.000.000.011
000.000.000.017
000.000.000.036
000.000.000.056
000.000.000.066
000.000.000.094
000.000.000.115
000.000.000.121
000.000.000.136
000.000.000.141
000.000.000.157
000.000.000.169
000.000.000.178
000.000.000.181
000.000.000.183
000.000.000.208
000.000.000.227
000.000.000.230
000.000.000.283
000.000.000.312
000.000.000.354
000.000.000.361
000.000.000.368
000.000.000.370
000.000.000.505
000.000.000.515
000.000.000.579
000.000.000.580
000.000.000.588
000.000.000.610
000.000.000.634
000.000.000.642
000.000.000.651
000.000.000.748
000.000.000.756
000.000.000.758
000.000.000.772
000.000.000.795
000.000.000.814
000.000.000.852
000.000.000.878
000.000.000.882
000.000.000.922
000.000.000.994
000.000.000.995
000.000.001.047
000.000.001.119
000.000.001.139
000.000.001.185
000.000.001.198