日志文件
About 25% of the activity is 200-OKAbout 25% of the activity is 200-OKAbout 25% of the activity is 200-OKAbout 25% of the activity is 200-OK大约 25% 的活动是 200-OK
我发现我的网络服务器已经将一些日志文件保存了一年,有的保存了一个月。 我研究了三种类型的日志文件,其中包含有关服务器访问者的信息(还有其他文件似乎不太有趣)。 以下是一些典型示例:
这验证日志(IP 已更改)
Oct 23 06:02:24 server1 sshd[20172]: Failed password for invalid user admin from 192.168.1.1 port 64721 ssh2
Oct 23 06:09:01 server1 CRON[20181]: pam_unix(cron:session): session opened for user root by (uid=0)
Oct 23 06:09:01 server1 CRON[20181]: pam_unix(cron:session): session closed for user root
Oct 23 06:10:35 server1 sshd[20195]: Did not receive identification string from 192.168.1.1
Oct 23 06:10:40 server1 sshd[20196]: Invalid user admin from 192.168.1.1
Oct 23 06:10:40 server1 sshd[20196]: input_userauth_request: invalid user admin [preauth]
Oct 23 06:10:41 server1 sshd[20196]: pam_unix(sshd:auth): check pass; user unknown
Web 服务器上的授权尝试代表登录尝试,无论是由我、属于我的服务器上的软件(CRON,上面)还是其他人或计算机(某人尝试使用 admin 用户 ID,上面)进行的。 管理员属于“坏人”类别。
这访问日志(Apache 服务器)(IP 已更改)
192.168.2.2 - - [30/Aug/2016:08:30:29 -0400] "GET / HTTP/1.1" 200 1714 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /hndUnblock.cgi HTTP/1.0" 404 496 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /tmUnblock.cgi HTTP/1.0" 404 495 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /cgi/common.cgi HTTP/1.0" 404 496 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:53 -0400] "GET /stssys.htm HTTP/1.0" 404 492 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:53 -0400] "GET / HTTP/1.0" 200 1714 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:54 -0400] "POST /command.php HTTP/1.0" 404 493 "-" "Wget(linux)"
192.168.3.3 - - [30/Aug/2016:09:09:01 -0400] "GET /?feed=rss2 HTTP/1.1" 200 794 "-" "Feedly/1.0 (+http://www.feedly.com/fetcher.html; like FeedFetcher-Google)"
访问日志条目表示从服务器获取网页的尝试。 上面的第一行代表网络爬虫的有效请求(百度,一个中文搜索引擎)。 get 请求针对 / 这是主页。 200 表示页面服务正常。 接下来的六行都有 404(未找到)结果。 这是一名黑客试图找到配置错误的网络服务器。 经过几次尝试后,监控软件(Fail2Ban)注意到发生了什么并将他锁在门外。 我曾经认为 Fail2Ban 非常重要(现在仍然如此!),但后来我发现了 UFW,简单的防火墙,以及一个更大的威胁。
这是UFW日志:
Oct 9 04:35:21 server1 kernel: [5110701.311961] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.9.9.9 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=40 ID=53848 DF PROTO=TCP SPT=10651 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:35:24 server1 kernel: [5110704.311558] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.8.8.8 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=40 ID=53849 DF PROTO=TCP SPT=10651 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:35:36 server1 kernel: [5110715.912365] [UFW BLOCK] IN=venet0 OUT= MAC= src=112.7.7.7 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=39 ID=32234 PROTO=TCP SPT=60061 DPT=23 WINDOW=16244 RES=0x00 SYN URGP=0
Oct 9 04:35:46 server1 kernel: [5110726.213736] [UFW BLOCK] IN=venet0 OUT= MAC= src=67.6.6.6 DST=192.168.1.1 LEN=44 TOS=0x00 PREC=0x40 TTL=239 ID=7084 PROTO=TCP SPT=57510 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0
Oct 9 04:37:02 server1 kernel: [5110802.146865] [UFW BLOCK] IN=venet0 OUT= MAC= src=139.5.5.5 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=39 ID=33753 PROTO=TCP SPT=6885 DPT=23 WINDOW=9693 RES=0x00 SYN URGP=0
Oct 9 04:37:53 server1 kernel: [5110853.056320] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.4.4.4 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61204 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:37:56 server1 kernel: [5110856.056659] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.3.3.3 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61205 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:38:02 server1 kernel: [5110862.056195] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.2.2.2 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61206 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:39:04 server1 kernel: [5110924.610656] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.1.1.1 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=43 ID=16953 PROTO=TCP SPT=35941 DPT=23 WINDOW=41293 RES=0x00 SYN URGP=0
UFW BLOCK 行的每一行都代表对服务器的另一种攻击:寻找配置错误的端口。 所有这些行都在测试 DPT=23,即远程登录,一种古老的协议。 请注意,这种情况至少每分钟发生一次。 整天。 每天。
将数据加载到数据表中
每个文件的格式不同,日期可能不包含当前年份,字段可能具有名称=值或只是位置。 我将所有文件从 Linux 服务器移至 Windows 计算机,并使用 FilesInDirectory 获取 JSL 中的文件名列表。 然后我编写了一组模式来有效地解析这三种类型的文件。 选择数据表列来表示我想要从每个文件中捕获的数据:
Columns in tableColumns in tableColumns in tableColumns in table表中的列
ipaddr32 是一个公式列,用于将 1.2.3.4 转换为图形上连续轴的 1<<24 + 2<<16 + 3<<8 + 4。稍后将查找 ipname。 kind2 是一个将所有不同的用户 ID 简化为“登录”的公式。
path = "f:/logs/";
list = Files In Directory( path, "recursive" );
global:dt = New Table( "logData",
New Column( "datetime", Numeric, "Continuous", Format( "ddMonyyyy:h:m:s", 18, 0 ), Input Format( "ddMonyyyy:h:m:s", 0 )),
New Column( "ipaddr", Character, "Nominal" ),
New Column( "kind", Character, "Nominal" ),
New Column( "detail1", Character, "Nominal" ),
New Column( "detail2", Character, "Nominal" )
);
高效解析
为了获得大文件的最大速度,JSL 解析需要在单个 PatMatch 函数调用中完成。 每次调用 PatMatch 都会产生一些开销,如果您进行多次调用,那么您也可能会在调用时切割输入字符串,这会增加更多开销。 因此,让每个日志文件使用一个 PatMatch 来完成此操作。 键是两个模式匹配函数:PatRepeat 和 PatTest。 PatRepeat 将使文件中的每一行重复该模式。 PatTest 会让模式在比赛期间运行一些 JSL(名义上是为了测试条件,但我们的测试结果将始终为“true”)。 一些辅助模式,然后进入好东西......
ipPattern = patRegex("(\d{1,3}[-.]\d{1,3}[-.]\d{1,3}[-.]\d{1,3})|([a-fA-F0-9:]+)"); // approximation
ipMonth=patRegex("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec");
datePattern1 = "[" + patregex("\d{2}")>>day + "/" + ipMonth>>month + "/" + patregex("\d{4}")>>year + ":" + patregex("\d\d:\d\d:\d\d")>>time + patregex(" [-+]\d{4}") +"]"; // [18/Sep/2016:06:14:25 -0400]
datePattern2 = ipMonth>>month + patspan(" ") + patregex("\d{1,2}")>>day + " " + patregex("\d\d:\d\d:\d\d")>>time + pattest(year="2016";1); //vs Oct 16 04:54:31 the unknown year is 2016 for these logs
quote = "\!"";
quotepattern = quote + patrepeat(patbreak(quote||"\") +(("\"+(quote|""))|"")) + quote; // allows \" escaped embedded quotation marks
两个日期模式与两种日期格式匹配。 >> 运算符将左侧匹配的文本放入右侧的变量中。 PatTest(year="2016";1) 在将 2016 分配给年份后始终返回 true;这是针对没有明确年份的日志文件。 我使用模式和正则表达式的混合搭配来构建越来越大的模式。 这是 Apache access.log 模式:
apachePat = ipPattern>>ip+" "+patbreak(" ")+" "+patbreak(" ")+" "
+datePattern1+" "
+quotePattern>>request+" "
+patbreak(" ")>>code+" "
+patbreak(" ")>>length+" "+patbreak(" ")+" "
+(quotePattern|patbreak("\!n\!r"))>>browser
+pattest(
dt1<<ADDROWS></ADDROWS>
将其作用与 access.log 中的一行进行比较
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /tmUnblock.cgi HTTP/1.0" 404 495 "-" "Wget(linux)"
并注意最后的 pattest(...) ;它向表 dt1 添加一行,并使用刚刚解析的值填充列。
还有 UFW 和 auth 模式。 这是解析文件的函数:
global:skipPattern = (patbreak("\!n\!r") + patlen(1))>> unknown + pattest(show(filename,unknown);stop();1);
global:whitespace = patregex("\s*");
parser = Function( {filename, pattern, dt1}, {Default Local},
txt = Load Text File( filename );
rc = Pat Match( //
txt, //
Pat Pos( 0 ) //
+ Pat Repeat( ((global:whitespace + pattern + global:whitespace) | global:skipPattern) + Pat Fence() ) //
+ Pat R Pos( 0 ) //
); //
);
该函数从文件名加载日志并使用模式参数对其进行解析并将结果存储在 dt1 中。 PatMatch 函数构建一个交替模式,允许跳过无法识别的行。 PatFence() 是针对大文件的另一种优化;这意味着“如果你已经走到这一步,就没有必要备份并尝试不同的东西”,它既可以加快比赛速度,又可以减少所需的内存。 最后,这是该函数的驱动程序:
While( N Items( file = Remove From( list, 1 ) ) == 1, //
file = file[1];//
If(//
!Is Missing( Regex( file, "ssl_access.log" ) ), //
parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "other_vhosts_access.log" ) ), //
0//parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "access.log" ) ), //
parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "ufw.log" ) ),
parser( path || file, ufwPat, global:dt );//
, // else
!Is Missing( Regex( file, "auth.log" ) ), //
parser( path || file, authPat, global:dt );//
);//
);//
兴趣点
Raspberry PI 计算机似乎吸引了大量使用用户名 PI 的攻击。 PHP 脚本肯定经常被错误配置;对于某些 PHP“管理”文件有很多检查。 找到一个有弱点的开放端口一定非常有价值;绝大多数攻击都是测试端口。 如果您管理 Web 服务器并且不使用fail2ban 和防火墙规则(如 UFW),则应考虑安装和配置它们。 您可以通过每天允许尝试几次而不是每秒尝试多次来减慢暴力攻击的速度。
Dashboard view of web trafficDashboard view of web trafficDashboard view of web trafficDashboard view of web traffic网络流量的仪表板视图