天天看點

Web伺服器⽇志特征提取

在典型的 Web 伺服器上,你會在 /var/log/apache2/ 中找到 Apache ⽇志,通常是access.log 、 ssl_access.log (對于 HTTPS)或 gzip 壓縮後的輪轉⽇志⽂件,如 access-20200101.gz 或者 ssl_access-20200101.gz 。

HTTP伺服器記錄什麼⽇志資訊可以配置的。參考簡書:web通路⽇志分析

1)Apache采⽤如何配置⽣成⽇志

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{UserAgent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
           

2)nginx采⽤如何配置⽣成⽇志

log_format main '$remote_addr - $remote_user [$time_local] "$request"
'
 '$status $body_bytes_sent "$http_referer" '
 '"$http_user_agent" "$http_x_forwarded_for"';
           

伺服器⽇志常采⽤Common Log Format (CLF) 或 Extended Log Format (ELF) 格式。

1)通⽤⽇志格式 common log format

127.0.0.1 - - [14/May/2017:12:45:29 +0800] "GET /index.html HTTP/1.1" 200 4286
遠端主機IP 請求時間 時區 ⽅法 資源 協定 狀态碼 發送位元組
           
Web伺服器⽇志特征提取

2)組合⽇志格式 combined log format

127.0.0.1 - - [14/May/2017:12:51:13 +0800] "GET /index.html HTTP/1.1"
200 4286 "http://127.0.0.1/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116
Safari/537.36"
遠端主機IP 請求時間 時區 ⽅法 資源 協定 狀态
碼 發送位元組 referer字元 浏覽器資訊
           

其中,有關鍵的資訊:⽇志狀态碼。

2XX:

200: 請求成功
 201: 建立成功
 202: 接受請求
 204: ⽆内容
           

3XX

301: 永遠重定向
302: 臨時重定向
303: 臨時重定向(HTTP1.1 同302)
307: 臨時重定向(HTTP1.1 POST⽅法)
           

4XX

400: 錯誤請求
 401: 通路拒絕
 403: 通路禁⽌
 404: 未找到
 405: 請求⽅法錯誤
           

5XX

500: 伺服器内部錯誤
 503: 服務不可⽤
 505: ⽹關逾時
           

平時應急響應的時候可以利⽤⼀些Python⼩⼯具來使得⼯作事半功倍,⽹上⼀些⽐較優秀的web⽇志分析⼯具,可以在web系統中故障排查、性能分析⽅⾯有着⾮常重要的作⽤。可以在指定時間段内提供細粒度(最⼩分鐘級别,即⼀分鐘内的⽇志做抽象和彙總)的異常定位和性能分析。⽐如:使⽤這個 Python ⼯具分析你的 Web 伺服器⽇志⽂件。Lars 是 Python 寫的 Web 伺服器⽇志⼯具包。這意味着你可以使⽤ Python 通過簡單的代碼來回溯(或實時)解析⽇志,并對資料做任何你想做的事:将它存儲在資料庫中、另存為 CSV ⽂件,或者⽴即使⽤ Python 進⾏更多分析。

下面是給出一個初步的提取樣例(并不是非常專業,部落客還在入門階段)

from lars import apache,datatypes
from datetime import datetime, date
import pandas as pd
import os
import time
import glob
import csv

class web_log(object):
    def __init__(self, fp):
        self.file=open('net1.log')

    def get_log_feature(self, num=None):
        index=0
        with apache.ApacheSource(self.file,log_format=apache.COMBINED) as source:
            for row in source:
                #print("index:",index)
                client_IP=datatypes.ipaddress.native_str(row.remote_host) #<class 'lars.datatypes.ipaddress.IPv4Address'>
                #print("client_IP:",client_IP,type(client_IP))

                bytes_size=str(row.size)
                #print("bytes_size:",bytes_size,type(bytes_size))

                referrer=str(row.req_Referer) #<class 'lars.datatypes.url.Url'>

                #print("referrer:",referrer,type(referrer))

                client_UA=str(row.req_User_agent)
                #print("client_UA",client_UA,type(client_UA))

                request_Type=row.request.method
                #print("request_Type",request_Type,type(request_Type))

                time=row.time #<class 'lars.datatypes.datetime.DateTime'>
                Timestamp = str(datatypes.DateTime.timestamp(time))
                #print("time",time,type(time),"timestamp:",Timestamp,type(Timestamp))


                HTTP_protocol_version=str(row.request.protocol)
               #print('HTTP_protocol_version:',HTTP_protocol_version,type(HTTP_protocol_version))

                url=str(row.request.url) #<class 'lars.datatypes.url.Url'>
                #print("url:",url,type(url))

                http_status_code=str(row.status)
                #print("http_status_code:",http_status_code,type(http_status_code))
                index+=1
                if num:  # 如果指定num=100,則隻會輸出100個流
                    if index >= num:
                        return[client_IP,bytes_size,referrer,request_Type,Timestamp,
                           HTTP_protocol_version,url,http_status_code,client_UA]
                    yield [client_IP,bytes_size,referrer,request_Type,Timestamp,
                           HTTP_protocol_version,url,http_status_code,client_UA]


if __name__ == '__main__':

        log_file = "net1.log"
        web_logs = web_log(log_file)
        log_features=web_logs.get_log_feature(num=100);
        with open("net_log_features.csv", 'w') as f:  # 将提取出的特征組儲存起來
            f.write("client_IP,bytes_size,referrer,request_Type,timestamp, HTTP_protocol_version,url,http_status_code,client_UA\r")
            writer=csv.writer(f)
            for log_feature in log_features:
                print(log_feature)
                #write_str = ",".join(log_feature)
                writer.writerow(log_feature)

            f.close()

           

提取出的csv檔案大緻如下:

Web伺服器⽇志特征提取

過程中遇到的問題:

在提取過程中,對于lars包定義的資料格式并不了解。詳見

https://lars.readthedocs.io/en/latest/lars.datatypes.html

關于lars定義的其它使用方法也會在其中有一定表述