Skip to content
Snippets Groups Projects
Commit 65672fb2 authored by Stuart Gathman's avatar Stuart Gathman
Browse files

Update log parser for new ops, etc

parent 155eb4e6
No related branches found
No related tags found
No related merge requests found
# Analyze milter log to find abusers # Analyze milter log to find abusers
import traceback
import sys
def parse_addr(a):
beg = a.find('<')
end = a.find('>')
if beg >= 0:
if end > beg: return a[beg+1:end]
return a
class Connection(object); class Connection(object):
def __init__(self,dt,tm,id,ip) def __init__(self,dt,tm,id,ip=None,conn=None):
self.dt = dt self.dt = dt
self.tm = tm self.tm = tm
self.id = id self.id = id
if ip:
_,self.host,self.ip = ip.split(None,2) _,self.host,self.ip = ip.split(None,2)
elif conn:
self.ip = conn.ip
self.host = conn.host
self.helo = conn.helo
self.subject = None
self.rcpt = []
self.mfrom = None
self.helo = None
self.innoc = []
self.whitelist = False
def connections(fp): def connections(fp):
conndict = {} conndict = {}
termdict = {}
for line in fp: for line in fp:
if line.startswith('{'): continue
a = line.split(None,4) a = line.split(None,4)
if len(a) < 4: continue if len(a) < 4: continue
dt,tm,id,op = a[:4] dt,tm,id,op = a[:4]
if id,op == 'bms','milter': if (id,op) == ('bms','milter'):
# FIXME: optionally yield all partial connections # FIXME: optionally yield all partial connections in conndict
conndict = {} conndict = {}
key = id termdict = {}
continue
if id[0] == '[' and id[-1] == ']':
try:
key = int(id[1:-1])
except:
print >>sys.stderr,'bad id:',line.rstrip()
continue
else: continue
if op == 'connect': if op == 'connect':
ip = a[4].rstrip() ip = a[4].rstrip()
conn = Connection(dt,tm,id,ip) conn = Connection(dt,tm,id,ip=ip)
conndict[key] = conn conndict[key] = conn
elif op in (
'DISCARD:','TAG:','CBV:','Large','No',
'NOTE:','From:','Sender:','TRAIN:'):
continue
else: else:
op = op.lower()
try:
conn = conndict[key] conn = conndict[key]
if op == 'Subject:': except KeyError:
if len(a) > 4: conn.subject = a[4].rstrip() try:
conn = termdict[key]
del termdict[key]
conndict[key] = conn
except KeyError:
print >>sys.stderr,'key error:',line.rstrip()
continue
try:
if op == 'subject:':
if len(a) > 4:
conn.subject = a[4].rstrip()
elif op == 'innoc:':
conn.innoc.append(a[4].rstrip())
elif op == 'whitelist':
conn.whitelist = True
elif op == 'x-mailer:':
if len(a) > 4:
conn.mailer = a[4].rstrip()
elif op == 'x-guessed-spf:':
conn.spfguess = a[4]
elif op == 'received-spf:':
conn.spfres,conn.spfmsg = a[4].rstrip().split(None,1)
elif op == 'received:':
conn.received = a[4].rstrip()
elif op == 'temp':
_,conn.tempfile = a[4].rstrip().split(None,1)
elif op == 'srs':
_,conn.srsrcpt = a[4].rstrip().split(None,1)
elif op == 'mail': elif op == 'mail':
_,conn.mfrom = a[4].split(None,2) _,conn.mfrom = a[4].rstrip().split(None,1)
elif op == 'rcpt': elif op == 'rcpt':
_,conn.rcpt = a[4].split(None,2) _,rcpt = a[4].rstrip().split(None,1)
conn.rcpt.append(rcpt)
elif op == 'hello':
_,conn.helo = a[4].rstrip().split(None,1)
elif op in ('eom','dspam','abort'): elif op in ('eom','dspam','abort'):
del conndict[key] del conndict[key]
conn.enddt = dt conn.enddt = dt
conn.endtm = tm conn.endtm = tm
conn.result = op conn.result = op
yield conn yield conn
elif op in ('REJECT:','DSPAM:','SPAM:'): termdict[key] = Connection(conn.dt,conn.tm,conn.id,conn=conn)
elif op in ('reject:','dspam:','tempfail:','reject','fail:','honeypot:'):
del conndict[key]
conn.enddt = dt conn.enddt = dt
conn.endtm = tm conn.endtm = tm
conn.result = op conn.result = op
conn.resmsg = a[4].rstrip() conn.resmsg = a[4].rstrip()
yield conn yield conn
termdict[key] = Connection(conn.dt,conn.tm,conn.id,conn=conn)
elif op in ('fp:','spam:'):
del conndict[key]
termdict[key] = Connection(conn.dt,conn.tm,conn.id,conn=conn)
else: else:
print line.rstrip() print >>sys.stderr,'unknown op:',line.rstrip()
except Exception:
print >>sys.stderr,'error:',line.rstrip()
traceback.print_exc()
if __name__ == '__main__': if __name__ == '__main__':
import gzip import gzip
import sys for fn in sys.argv[1:]:
for fn in sys.argv[:1]:
if fn.endswith('.gz'): if fn.endswith('.gz'):
fp = gzip.open(fn) fp = gzip.open(fn)
else: else:
fp = open(fn) fp = open(fn)
for conn in connections(fp): for conn in connections(fp):
print conn.dt,conn.tm,conn.id,conn.subject,conn.mfrom,conn.rcpt if conn.rcpt and conn.mfrom:
for r in conn.rcpt:
if r.lower().find('iancarter') > 0: break
else:
if conn.mfrom.lower().find('iancarter') < 0: continue
print >>sys.stderr,conn.result,conn.dt,conn.tm,conn.id,conn.subject,parse_addr(conn.mfrom),
for a in conn.rcpt:
print parse_addr(a),
print
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment