DMARC und Mailinglisten

Joachim Fahrner jf at fahrner.name
So Feb 22 08:05:19 CET 2015


Am 21.02.2015 um 23:17 schrieb Robert Schetterer:
>
>  hm , ich habe es absichtlich in use , seit ein paar Monaten und noch
> keine Probleme damit , allerdings ist es ein low Traffic Server,
> schwierig da Aussagen zum machen, auf jeden Fall operiert Dmarc schon am
> Rande was technisch grade noch so geht und verkompliziert Mail doch
> erheblich, ich kann jeden verstehen der das zur Zeit noch nicht einsetzt.
>

Ich hab mir damals im September, als ich mit den Bugs im OpenDMARC
gekämpft habe, ein kleines Python-Script zum auswerten des Maillogs
gemacht, um zu sehen was alles warum abgewiesen wurde. Ich hab das
Script mal angehängt, vielleicht findet es jemand nützlich (hoffentlich
verträgt die Liste Anhänge).

Mit dem Script schaue ich mir regelmässig das Log an. Wegen DMARC wurde
bisher noch keine Mail abgewiesen (ausser jetzt die false positives aus
der Liste). Von daher kann man glaube ich gut drauf verzichten. :-D

-- 
Mit besten Grüßen
Joachim Fahrner

-------------- nächster Teil --------------
#!/usr/bin/env python
#-*-coding: utf-8 -*-

import sys
import re
import GeoIP

global logfile
global abgewiesen
global ipstat
global cystat
global tostat

gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
gi6 = GeoIP.open("/usr/share/GeoIP/GeoIPv6.dat",GeoIP.GEOIP_STANDARD)

def land(ip):
	trans = { 'United States':'USA',
			  'United Kingdom':'England',
			  'Brunei Darussalam':'Brunei',
			  'Hong Kong':'Hongkong',
			  'United Arab Emirates':'Arabien',
			  'Czech Republic':'Tschechien',
			  'Dominican Republic':'Dom.Rep.',
			  'Palestinian Territory':'Palestina',
			  'South Africa':'Südafrika',
			  'Cote D\'Ivoire':'Elfenbeinküste',
			  'Trinidad and Tobago':'Trinidad',
			  'Russian Federation':'Russland',
			  'Saudi Arabia':'S.Arabien',
			  'Switzerland':'Schweiz' }
	if ip.find(':') == -1:
		l = gi.country_name_by_addr(ip)
	else:
		l = gi6.country_name_by_addr_v6(ip)
	if l == None:
		return ''
	if ',' in l:
		(l1,l2) = l.split(',',2)
		l = l1
	try:
		ll = trans[l]
	except KeyError:
		ll = l
	return ll

def getvars(msg):
	vars = {'from':'null', 'to':'null', 'ip':'', 'land':''}
	s = msg.split()
	for token in s:
		if token[-1] == ',':
			token = token[:-1]
		if "=" in token:
			(var,value) = token.split('=',1)
			vars[var] = value
	#IP und Land
	m = re.search('\[([0-9.]+)\]',msg)
	if m == None:
		m = re.search('\[([0-9a-f:]+)\]',msg)
	if m != None:
		vars['ip'] = m.group(1)
		countip(m.group(1))
		lnd = land(m.group(1))
		countcy(lnd)
		vars['land'] = lnd

	countto(vars['to'])
	return vars

def countto(to):
	global tostat
	if to in tostat:
		tostat[to] += 1
	else:
		tostat[to] = 1

def countip(ip):
	global ipstat
	if ip in ipstat:
		ipstat[ip] += 1
	else:
		ipstat[ip] = 1

def countcy(cy):
	global cystat
	if cy in cystat:
		cystat[cy] += 1
	else:
		cystat[cy] = 1

def log(typ,date,server,msg):
	global abgewiesen
	vars = getvars(msg)
	print "{1:s} {0:8s} from={3:25.25s} to={2:25.25s} ip={4:15s} {5:s}".format(typ,date,vars['to'],vars['from'],vars['ip'],vars['land'])
	abgewiesen += 1

def noqueue(date,server,msg):
	if 'rejected: Greylisted' in msg:  # Greylist ist ok
		return
	if 'RBLTRAP' in msg:
		log('RBLTRAP:',date,server,msg)
	elif 'Helo command rejected:' in msg:
		log('HELO:',date,server,msg)
	elif 'Client host rejected:' in msg:
		log('CLIENT:',date,server,msg)
	elif 'Relay access denied' in msg:
		log('RELAY:',date,server,msg)
	elif 'Sender address rejected:' in msg:
		log('SENDER:',date,server,msg)
	elif 'SPF fail' in msg:
		log('SPF:',date,server,msg)
	else:
		log('???',date,server,msg)

def smtpd(date,server,msg):
	if msg[0:8] == 'NOQUEUE:':
		noqueue(date,server,msg)

def postscreen(date,server,msg):
	if msg[0:8] == 'NOQUEUE:':
		psnoqueue(date,server,msg)

def psnoqueue(date,server,msg):
	if 'blocked using' in msg:
		log('rbltrap:',date,server,msg)
	elif 'Protocol error;' in msg:
		log('protcol:',date,server,msg)
	else:
		log('???',date,server,msg)

def milterreject(date,server,msg):
	if 'DMARC policy' in msg:
		log('DMARC:',date,server,msg)
	elif 'Blocked by SpamAssassin' in msg:
		log('SPAMAS:',date,server,msg)
	else:
		log('MILTER:',date,server,msg)
		
def cleanup(date,server,msg):
	if 'milter-reject:' in msg:
		milterreject(date,server,msg)
	elif 'reject:' in msg:
		log('CLEANUP:',date,server,msg)
		
def main():
	global logfile, abgewiesen, ipstat, cystat, tostat
	gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
	abgewiesen = 0
	ipstat = {}
	cystat = {}
	tostat = {}
	f = open(logfile,'r')
	for line in f:
		i = line.find(': ')
		if i <> -1:
			s1 = line[0:i]
			msg = line[i+2:]
			ss = s1.split()
			date = ss[0] + ' ' + ss[1] + ' ' + ss[2]
			server = ss[4]
			i = server.find('[')
			if i <> -1:
				server = server[0:i]
			if server == 'postfix/smtpd':
				smtpd(date,server,msg)
			elif server == 'postfix/postscreen':
				postscreen(date,server,msg)
			elif server == 'postfix/cleanup':
				cleanup(date,server,msg)
		else:
			print line
	print "{0:d} abgewiesene Mails".format(abgewiesen)
	#for ip in ipstat:
	#	land = gi.country_name_by_addr(ip)
	#	print "{0:s} : {1:d} mal ({2:s})".format(ip,ipstat[ip],land)
	#for cy in cystat:
	#	print "{0:s} : {1:d} mal".format(cy,cystat[cy])
	for to in tostat:
		print "{0:s} : {1:d} mal".format(to,tostat[to])
		
if len(sys.argv) < 2:
	logfile = '/var/log/mail.log'
else:
	if "/" in sys.argv[1]:
		logfile = sys.argv[1]
	else:
		logfile = "/var/log/" + sys.argv[1]
	
main()


Mehr Informationen über die Mailingliste postfix-users