# 2010-11-11a # Only Python 3.x or the greater import datetime import re import socket import sys import time import traceback SyslogFacilities = { "kern":0<<3, "user":1<<3, "mail":2<<3, "daemon":3<<3, "auth":4<<3, "syslog":5<<3, "lpr":6<<3, "news":7<<3, "uucp":8<<3, "cron":9<<3, "authpriv":10<<3, "ftp":11<<3, # 12 - 15 is reserved. "local0":16<<3, "local1":17<<3, "local2":18<<3, "local3":19<<3, "local4":20<<3, "local5":21<<3, "local6":22<<3, "local7":23<<3, } SyslogSeverities = { "emergency":0, "emerg":0, "alert":1, "critical":2, "error":3, "warn":4, "warning":4, "notice":5, "notification":5, "info":6, "information":6, "debut":7 } # ---------- Log Format Definitions ---------- lfdict = { # WELF r'(.*\s)?(id=[^\s]+\stime="?)(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(.+pri=)([0-7])(\s.+)' : lambda m,d: '<' + str(SyslogFacilities['local7'] | int(m.group(5))) + '>' + m.group(2) + d.strftime("%Y-%m-%d %H:%M:%S") + m.group(4) + m.group(5) + m.group(6), # NetScreen Native1 r'(.*\s)?([^\]]+: NetScreen device_id=[^\s]+\s+\[[^\s]+\]system-)(\w+)(-.+start_time=")(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(.*)' : lambda m,d: '<' + str(SyslogFacilities["local7"] | SyslogSeverities[m.group(3).lower()]) + '>' + m.group(2) + m.group(3) + m.group(4) + d.strftime("%Y-%m-%d %H:%M:%S") + m.group(6), # NetScreen Native2 r'(.*\s)?([^\]]+: NetScreen device_id=[^\s]+\s+\[[^\s]+\]system-)(\w+)(-.+\()(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(\).*)' : lambda m,d: '<' + str(SyslogFacilities["local7"] | SyslogSeverities[m.group(3).lower()]) + '>' + m.group(2) + m.group(3) + m.group(4) + d.strftime("%Y-%m-%d %H:%M:%S") + m.group(6), # IPCOM Native r'((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{2} \d{2}:\d{2}:\d{2})( \S+ IPCOM.+)(' + '|'.join(SyslogSeverities).upper() + ')(\[.*)' : lambda m,d: '<' + str(SyslogFacilities["local7"] | SyslogSeverities[m.group(4).lower()]) + '>' + d.strftime('%b %d %H:%M:%S') + m.group(3) + m.group(4) + m.group(5), # FortiGate Native r'(.*)(date=)(\d{4}-\d{2}-\d{2})( time=)(\d{2}:\d{2}:\d{2})( device_id=.*)( pri=)(\w+)( .*)' : lambda m,d: '<' + str(SyslogFacilities["local7"] | SyslogSeverities[m.group(8).lower()]) + '>' + m.group(2) + d.strftime("%Y-%m-%d") + m.group(4) + d.strftime("%H:%M:%S") + m.group(6) + m.group(7) + m.group(8) + m.group(9), # Cisco PIX/ASA r'(.*)(%(ASA|FWSM|PIX)\-)(\d)(-.*)' : lambda m,d: '<' + str(SyslogFacilities['local7'] | int(m.group(4))) + '>' + m.group(2) + m.group(4) + m.group(5), # Barracuda WAF r'([a-zA-Z]+ )(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(\.\d{3}.*)' : lambda m,d: '<' + str(SyslogFacilities['local7'] | SyslogSeverities['warn']) + '>' + m.group(1) + d.strftime('%Y-%m-%d %H:%M:%S') + m.group(3), # Linux r'^[A-Z][a-z]{2} [0-9 ]\d \d{2}:\d{2}:\d{2} (.+)' : lambda m,d: '<' + str(SyslogFacilities['local7'] | SyslogSeverities['warn']) + '>' + m.group(1), } # -------------------------------------------- def get_opts(a): ''' sys.argv[1] = ip_address/tcp|udp:port sys.argv[2] = log_file_path if exists sys.argv[3] = interval_sec ''' # default value interval_sec = 1 protocol = 'udp' port = 514 logfile_encoding = sys.getfilesystemencoding() if len(a) == 4: interval_sec = float(a[3]) ipm = re.match('(\d+\.\d+\.\d+\.\d+)(.*)', a[1]) ip_address = ipm.group(1) if ipm.group(2) != None and ipm.group(2) != "": prm = re.match(':(tcp|udp)\/(\d+)', ipm.group(2), re.I) protocol = prm.group(1).lower() port = int(prm.group(2)) if ":" in a[2]: logfile_path, logfile_encoding = a[2].split(":") logfile_encoding = logfile_encoding.lower() else: logfile_path = a[2] return ip_address, protocol, port, logfile_path, logfile_encoding, interval_sec # -------------------------------------------- def make_a_sock(ip_addr, protocol, port, retry=0): s = None try: if protocol == 'udp': s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) elif protocol == 'tcp': s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip_addr, port)) except Exception as e: if retry < 3: print("Retrying to make the socket...") s = make_a_sock(ip_addr, protocol, port, retry+1) else: raise e return s # -------------------------------------------- s = None try: (ip_address, protocol, port, logfile_path, logfile_encoding, interval_sec) = get_opts(sys.argv) # print("""Target: %s:%s/%d #Log file: %s (%s) #Interval: %d #""" % (ip_address, protocol, port, logfile_path, logfile_encoding, interval_sec), end="") print("""Target: {0}:{1}/{2} Log file: {3} ({4}) Interval: {5} """.format(ip_address, protocol, port, logfile_path, logfile_encoding, interval_sec), end="") with open(logfile_path, mode="r", encoding=logfile_encoding, errors='ignore') as f: loglines = f.readlines() s = make_a_sock(ip_address, protocol, port) for l in loglines: ismatched = False l = l.rstrip('\r\n') if l != '': for rpat in lfdict: m = re.match(rpat, l) if m: try: s.sendall(lfdict[rpat](m, datetime.datetime.now()).encode(logfile_encoding)) ismatched = True time.sleep(interval_sec) break except KeyboardInterrupt as e: raise e except socket.error as e: print(e) s = make_a_sock(ip_address, protocol, port) continue except Exception as e: raise e if ismatched == False: print(l, file=sys.stderr) except KeyboardInterrupt as e: print("Keyborad Interrupted.") except socket.error as e: print(e) except Exception as e: traceback.print_exception(type(e), e, e.__traceback__) print(""" [Arguments] %s [Usage] sendlog.py [:(default=sys.getfilesystemencoding())] [interval_seconds(default=1)]""" % str(sys.argv)) finally: if s != None: s.close()