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