网络安全-华为华三交换机防火墙日志解析示例

DEF_SYSLOG_SWITCH_HUAWEI.py

华为交换机日志解析示例

# -*- coding: utf8 -*-
import time
from DEF_COLOR import *   ## 终端显示颜色


def 时间戳_2_时间文本(时间戳, 时间文本格式='%Y-%m-%d %H:%M:%S'):
    #时间文本格式 = '%Y-%m-%d %H:%M:%S'
    时间类 = time.localtime(时间戳)
    时间文本 = time.strftime(时间文本格式, 时间类)
    return(时间文本)

## 适用于需要在SYSLOG的时间上加上时区才能和本地时间相等的情况
def 日志时间转时间戳(时间文本, 加时区):
    时间戳 = time.mktime(time.strptime(时间文本, '%Y-%m-%dT%H:%M:%S'))+(3600*加时区)
    return(时间戳)

## 2022-11-28T19:00:51+08:00 主机名 %%01SHELL/5/LOGOUT(s)[3918]: The user succeeded in logging out of VTY0. (UserType=SSH, UserName=xxx, Ip=xxx.xxx.xxx.xxx, VpnName=)
def LOG_TYPE(LINE_TEXT):
    A = LINE_TEXT.find('%%')
    if A != -1:
        #打印_黄(LINE_TEXT[A:])
        B = LINE_TEXT.find('(', A)
        if B != -1:
            #打印_绿(LINE_TEXT[B:])
            C = LINE_TEXT.find(' ', B)  ## 找日志正文开始位置标志
            if C != -1:
                #打印_蓝(LINE_TEXT[C:])
                #打印_青(LINE_TEXT[A+4:B])
                SP = LINE_TEXT[A+4:B].split('/')
                return((SP[0], SP[2], C+1))
            else:
                打印_红(f"找位置标志' '失败(日志正文开始位) {LINE_TEXT}")
                return((' -1', LINE_TEXT[A:B], -1))
        else:
            打印_红(f"找位置标志'('失败 {LINE_TEXT}")
            return((LINE_TEXT[:A], '(-1', -1))
    else:
        A2 = LINE_TEXT.find(': OID')
        if A2 != -1:
            SP = LINE_TEXT[:A2].split()[-1].split('/')
            return((SP[0], SP[2], A2+1))
        else:
            打印_红(f"找位置标志'%%'失败且查找': OID'也失败 {LINE_TEXT}")
            return(('%-1', LINE_TEXT, -1))

# %%01ACLE/4/ACLLOG(l)[xxx]: Acl 3997 deny GigabitEthernet0/0/10 xxxx-xxxx-xxxx -> xxxx-xxxx-xxxx udp x.x.x.x(63877) -> 239.255.255.250(1900) (1 packet).
# %%01ACLE/4/ACLLOG(l)[xxx]: Acl 3997 deny GigabitEthernet0/0/10 xxxx-xxxx-xxxx -> xxxx-xxxx-xxxx igmp x.x.x.x -> 224.0.0.22 (4 packets).
# %%01ACLE/4/ACLLOG(l)[xxx]: Acl      deny GigabitEthernet0/0/14 xxxx-xxxx-xxxx -> xxxx-xxxx-xxxx tcp x.x.x.x(60559) -> x.x.x.x(80) (1 packet).
def ACLE_ACLLOG(D_SYSLOG_SWITCH_HUAWEI, LOG_MSG):
    SP = LOG_MSG.split()
    if len(SP) == 11:
        SP = ['X'] + SP     # 偶尔会丢个 acl id 补齐列表长度 'GigabitEthernet0/0/14 Acl'
    ACL_ID = SP[1]
    ACL_ST = SP[2]
    ACL_IF = SP[3]
    SMAC = SP[4]
    DMAC = SP[6]
    PT  = SP[7]
    SIP = SP[8].split('(')[0]   # 不记录源端口号
    DIP = SP[10].split('(')[0]  # 不记录目的端口号
    COUNT = int(SP[11][1:])
    K = (ACL_IF, ACL_ST, PT, f"{SIP}({SMAC})", f"{DIP}({DMAC})", ACL_ID)
    if K in D_SYSLOG_SWITCH_HUAWEI['D_ACL']['ACLE']:
        D_SYSLOG_SWITCH_HUAWEI['D_ACL']['ACLE'][K] += COUNT
    else:
        D_SYSLOG_SWITCH_HUAWEI['D_ACL']['ACLE'][K] = COUNT

# SACL/4/ACLLOG(l)[9487]: Acl 3996 applied Interface GigabitEthernet0/0/6 permit (15591 packets).
# SACL/4/ACLLOG(l)[6146]: Acl 3992 applied Interface  permit (2 packets).
# SACL/4/ACLLOG(l)[6112]: Acl 3992 applied Interface GigabitEthernet0/0/14 permit (174757578 packets).
def SACL_ACLLOG(D_SYSLOG_SWITCH_HUAWEI, LOG_MSG):
    try:
        SP = LOG_MSG.split()
        if len(SP) == 7:
            ACL_ID = SP[1]
            ACL_IF = SP[4]
            ACL_ST = SP[5]
            COUNT = int(SP[6][1:])
        elif len(SP) == 6:
            ACL_ID = SP[1]
            ACL_IF = 'un'
            ACL_ST = SP[4]
            COUNT = int(SP[5][1:])
        else:
            打印_红(f"ERROR LOG_MSG={LOG_MSG} SP={SP} len(SP)={len(SP)}")
        
        K = (ACL_IF, ACL_ST, ACL_ID)
        if K in D_SYSLOG_SWITCH_HUAWEI['D_ACL']['SACL']:
            D_SYSLOG_SWITCH_HUAWEI['D_ACL']['SACL'][K] += COUNT
        else:
            D_SYSLOG_SWITCH_HUAWEI['D_ACL']['SACL'][K] = COUNT
    except Exception as e:
        打印_红(f"ERROR {e} LOG_MSG={LOG_MSG} SP={SP} len(SP)={len(SP)}")
    else:
        pass

## 解析SYSLOG日志一行内容
def LINE_HUAWEI(D_SYSLOG_SWITCH_HUAWEI, LINE_TEXT, TIME_LOCAL):
    TP1, TP2, X = LOG_TYPE(LINE_TEXT)
    if TP1 == 'ACLE':
        if TP2 == 'ACLLOG':
            #打印_黄(LINE_TEXT[X:-1])
            ACLE_ACLLOG(D_SYSLOG_SWITCH_HUAWEI, LINE_TEXT[X:-10])
        else:
            return((1, TP1, TP2))   ## 终止,不做解析,返回标识代码及日志类型信息
    elif TP1 == 'SACL':
        if TP2 == 'ACLLOG':
            SACL_ACLLOG(D_SYSLOG_SWITCH_HUAWEI, LINE_TEXT[X:-10])
        else:
            return((1, TP1, TP2))
    elif TP1 == 'SHELL':
        if TP2 == 'LOGIN':                                 # The user succeeded in logging in to VTY0. (UserType=SSH, UserName=xxx, AuthenticationMethod="Local-user", Ip=xxx.xxx.xxx.xxx, VpnName=)
            SP = LINE_TEXT[X:-1].split(',')
            UserType = SP[0].split('=')[-1]
            UserName = SP[1].split('=')[-1]
            IP = SP[3].split('=')[-1]
            D_SYSLOG_SWITCH_HUAWEI['L_LOGIN'].append((TIME_LOCAL, 'LOGIN', UserType, UserName, IP))
        elif TP2 == 'LOGOUT':                              # The user succeeded in logging out of VTY0. (UserType=SSH, UserName=xxx, Ip=xxx.xxx.xxx.xxx, VpnName=)
            #print(TP1,TP2,LINE_TEXT[X:-1])
            SP = LINE_TEXT[X:-1].split(',')
            UserType = SP[0].split('=')[-1]
            UserName = SP[1].split('=')[-1]
            IP = SP[2].split('=')[-1]
            D_SYSLOG_SWITCH_HUAWEI['L_LOGIN'].append((TIME_LOCAL, 'LOGOUT', UserType, UserName, IP))
        elif TP2 in ('DISPLAY_CMDRECORD', 'CMDRECORD'):    # %%01SHELL/6/DISPLAY_CMDRECORD(s)[1869]: Recorded display command information. (Task=VT0, Ip=x.x.x.x, VpnName=, User=xx, AuthenticationMethod="Local-user", Command="display stp brief")
            SP = LINE_TEXT[X:].split(',')
            IP = SP[1].split('=')[-1]
            USER = SP[3].split('=')[-1]
            CMD = SP[5].split('=')[-1][:-2]
            #打印_青(f"(SHELL, {TP2}) {TIME_LOCAL} {IP} {USER} {CMD}")
            D_SYSLOG_SWITCH_HUAWEI['L_CMD'].append((TIME_LOCAL, IP, USER, CMD))
        elif TP2 == 'CMDCONFIRM_UNIFORMRECORD':            # %%01SHELL/6/CMDCONFIRM_UNIFORMRECORD(s)[1867]: Record command information. (Task=VT0, IP=x.x.x.x, VpnName=, User=xx, Command="", PromptInfo="The password needs to be changed. Change now? [Y/N]:", UserInput=N)
            SP = LINE_TEXT[X:].split(',')
            IP = SP[1].split('=')[-1]
            USER = SP[3].split('=')[-1]
            PromptInfo = SP[5].split('=')[-1]
            UserInput = SP[6].split('=')[-1][:-2]
            CMD = f"{PromptInfo} {UserInput}"
            #打印_青(f"(SHELL, {TP2}) {TIME_LOCAL} {IP} {USER} {CMD}")
            D_SYSLOG_SWITCH_HUAWEI['L_CMD'].append((TIME_LOCAL, IP, USER, CMD))
        else:
            return((1, TP1, TP2))
    elif TP1 == 'IFPDT':
        if TP2 == 'PKT_OUTDISCARD_ABNL':    ## 端口【出】方向丢包达到报警阈值
            SP = LINE_TEXT[X:].split(',')
            #for i in SP:
            #    print(i)
            SW_IF = SP[0].split('=')[-1]
            SW_DROP = SP[1].split('=')[-1]
            #print(SW_IF, SW_DROP, 'OUT')
            D_SYSLOG_SWITCH_HUAWEI['L_IF_DROP'].append((TIME_LOCAL, SW_IF, SW_DROP, 'OUT', '丢包超过阈值'))
        elif TP2 == 'PKT_OUTDISCARD_NL':    ## 端口【出】方向恢复正常
            SP = LINE_TEXT[X:].split(',')
            SW_IF = SP[0].split('=')[-1]
            SW_DROP = SP[1].split('=')[-1]
            #print(SW_IF, SW_DROP, 'OUT')
            D_SYSLOG_SWITCH_HUAWEI['L_IF_DROP'].append((TIME_LOCAL, SW_IF, SW_DROP, 'OUT', '恢复'))
        elif TP2 == 'PKT_INDISCARD_ABNL':   ## 端口【入】方向丢包达到报警阈值
            SP = LINE_TEXT[X:].split(',')
            #for i in SP:
            #    print(i)
            SW_IF = SP[0].split('=')[-1]
            SW_DROP = SP[1].split('=')[-1]
            #print(SW_IF, SW_DROP, 'IN')
            D_SYSLOG_SWITCH_HUAWEI['L_IF_DROP'].append((TIME_LOCAL, SW_IF, SW_DROP, 'IN', '丢包超过阈值'))
        elif TP2 == 'PKT_INDISCARD_NL':     ## 端口【入】方向恢复正常
            SP = LINE_TEXT[X:].split(',')
            SW_IF = SP[0].split('=')[-1]
            SW_DROP = SP[1].split('=')[-1]
            #print(SW_IF, SW_DROP, 'IN')
            D_SYSLOG_SWITCH_HUAWEI['L_IF_DROP'].append((TIME_LOCAL, SW_IF, SW_DROP, 'IN', '恢复'))
        elif TP2 == 'IF_STATE':
            SP = LINE_TEXT[X:].split()
            IF_ID = SP[1]
            IF_ST = SP[5]
            if IF_ID not in D_SYSLOG_SWITCH_HUAWEI['D_IF_PHY']:
                D_SYSLOG_SWITCH_HUAWEI['D_IF_PHY'][IF_ID] = []
            D_SYSLOG_SWITCH_HUAWEI['D_IF_PHY'][IF_ID].append((TIME_LOCAL, IF_ST))
        else:
            return((1, TP1, TP2))
    elif TP1 == 'SECE':
        D_SYSLOG_SWITCH_HUAWEI['L_SECE'].append(LINE_TEXT)
    elif TP1 == 'MSTP':
        D_SYSLOG_SWITCH_HUAWEI['L_STP'].append((TIME_LOCAL, LINE_TEXT[X:-1]))
    elif TP1 == 'IFNET':
        print('IFNET', TP2, TIME_LOCAL, LINE_TEXT[X:-1])
    elif TP1 == 'IFADP':
        print('IFADP', TP2, TIME_LOCAL, LINE_TEXT[X:-1])
    elif TP1 == 'SSH':
        if TP2 == 'SSH_TRANS_FILE_FINISH':
            D_SYSLOG_SWITCH_HUAWEI['L_FTP'].append((TIME_LOCAL, LINE_TEXT[X:-1]))
        else:
            return((1, TP1, TP2))
    elif TP1 == 'VTY':
        print('VTY', LINE_TEXT)
    else:
        return((1, TP1, TP2))
    return((0, TP1, TP2))

## 解析SYSLOG日志文件
def FILE_HUAWEI(D_SYSLOG_SWITCH_HUAWEI, FILE_PATH, TIME_STAMP_MIN, TIME_STAMP_MAX):
    #print("RUN", FILE_PATH, TIME_STAMP_MIN, TIME_STAMP_MAX)
    TIME_S = time.time()
    TOT_N = 0
    SELECT_N = 0
    解析数量 = 0
    for LINE_BYTES in open(FILE_PATH, mode='br'):
        TOT_N += 1
        try:
            LINE_TEXT = LINE_BYTES.decode('UTF-8')
        except Exception as e:
            打印_红(f"ERROR {TOT_N} LINE_BYTES={LINE_BYTES} {e}")
        else:
            TIME_UTC = LINE_TEXT[:19]
            #TIME_STAMP = time.mktime(time.strptime(TIME_UTC, '%Y-%m-%dT%H:%M:%S'))+28800
            TIME_STAMP = 日志时间转时间戳(TIME_UTC, 8)
            TIME_LOCAL = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(TIME_STAMP))
            if TIME_STAMP_MIN < TIME_STAMP < TIME_STAMP_MAX:
                SELECT_N += 1
                #print(TIME_UTC, TIME_LOCAL, 'RUN')
                ST,TP1,TP2 = LINE_HUAWEI(D_SYSLOG_SWITCH_HUAWEI, LINE_TEXT, TIME_LOCAL)
                if ST != 0:
                    #打印_红(f"{TOT_N} 未知LOG")
                    #break
                    if (TP1,TP2) in D_SYSLOG_SWITCH_HUAWEI['D_LOG_OTHER']:
                        D_SYSLOG_SWITCH_HUAWEI['D_LOG_OTHER'][(TP1,TP2)] += 1
                    else:
                        D_SYSLOG_SWITCH_HUAWEI['D_LOG_OTHER'][(TP1,TP2)] = 1
                else:
                    解析数量 += 1
            else:
                #print(TIME_UTC, TIME_LOCAL, 'PASS')
                pass
    TIME_RUN = time.time() - TIME_S
    #打印_绿(f"{FILE_PATH} 完成 处理日志数量 {SELECT_N}/{TOT_N} 筛选数/总日志数 用时={TIME_RUN:.2f}秒")
    return((FILE_PATH, TIME_STAMP_MIN, TIME_STAMP_MAX, TOT_N, SELECT_N, 解析数量, TIME_RUN))




def SYSLOG_SWITCH_HUAWEI(FILE_PATH, SHOW=0):
    D_SYSLOG_SWITCH_HUAWEI = {}
    D_SYSLOG_SWITCH_HUAWEI['D_ACL'] = {'ACLE':{}, 'SACL':{}} # ACL规则匹配记录
    D_SYSLOG_SWITCH_HUAWEI['D_IF_PHY'] = {}  # 接口物理断开记录
    D_SYSLOG_SWITCH_HUAWEI['D_IF_LINK'] = {} # 接口链路断开记录
    D_SYSLOG_SWITCH_HUAWEI['L_CMD'] = []     # 用户执行命令记录
    D_SYSLOG_SWITCH_HUAWEI['L_LOGIN'] = []   # 登录信息
    D_SYSLOG_SWITCH_HUAWEI['L_STP'] = []     # 生成树信息
    D_SYSLOG_SWITCH_HUAWEI['L_IF_DROP'] = [] # 接口丢包
    D_SYSLOG_SWITCH_HUAWEI['L_SECE'] = []    # 安全事件
    D_SYSLOG_SWITCH_HUAWEI['L_FTP'] = []
    D_SYSLOG_SWITCH_HUAWEI['D_LOG_OTHER'] = {} # 未解析日志记录
    
    TIME_STAMP_MIN = 0
    TIME_STAMP_MAX 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值