IT-Blog von Sebastian van de Meer

Kategorie: Kernel-Error-Blog (Seite 28 von 49)

Persönlicher Tech-Blog von Sebastian van de Meer — Beiträge zu IT-Security, Netzwerken, FreeBSD, Linux, Elektronik und Maker-Projekten.

Exchange Online, Lync Online und Office 365: DNS-Einträge für eine BIND-Zone einrichten

Bei mir ist gerade die Frage aufgeschlagen was man denn bitte in seine DNS Zone vom Bind schreiben muss, wenn man eines oder mehrere dieser wunderbaren Microsoft Lync, Office 365 oder Exchange benutzen möchte.
Während des Registrierungsprozesses kommt man an die Stelle an welcher man einen TXT RECORD in der Zone veröffentlichen soll um den besitzt der Domain/Zone zu bestätigen. Etwas später müssen dann für die einzelnen Dienste ebenfalls Records gesetzt werden, damit am Ende das Outlook Autodiscover, Lyncdiscover sowie die  Lync Federation funktionieren. Nutzt man Exchange Online muss natürlich noch der MX RECORD geändert werden, damit die E-Mails alle bei Microsoft „einlaufen“.

Nun ist es für ungeübte nicht immer direkt zu durchschauen was gemacht werden muss, daher hier ein kleines Beispiel an der Domain: kernel-error.com
Die zu setzenden RECORDS werden einem dann auf der Webseite von Microsoft wie im Beispiel unten Angezeigt.

Exchange Online

TypPrioritätHostnameVerweist auf die AdresseGültigkeitsdauer
MX 0 @ kernel-error-com0i.mail.protection.outlook.com 1 Stunde 
CNAME – autodiscover autodiscover.outlook.com 1 Stunde 
     
TypTXT-NameTXT-WertGültigkeitsdauer 
 TXT @ v=spf1 include:spf.protection.outlook.com -all 1 Stunde 
     
 Alias oder Hostname  Ziel Gültigkeitsdauer   
 kernel-error.com MS=ms12345678  1 Stunde
  

Lync Online

TypDienstProtokollPortStärkePrioritätGültigkeitsdauerNameZiel
SRV _sip _tls44311001 Stundekernel-error.comsipdir.online.lync.com
SRV _sipfederationtls _tcp506111001 Stundekernel-error.comsipfed.online.lync.com
         
 Typ Hostname Verweist auf die Adresse Gültigkeitsdauer     
 CNAME sip.kernel-error.com sipdir.online.lync.com 1 Stunde     
 CNAME lyncdiscover.kernel-error.com webdir.online.lync.com 1 Stunde     

Zusätzliche Office 365-Einträge

TypHostnameVerweist auf die AdresseGültigkeitsdauer
CNAMEmsoid.kernel-error.comclientconfig.microsoftonline-p.net1 Stunde

Ich LIEBE es ja, immer wenn Microsoft solche Dinge ins Deutsche übersetzten tongue-out Im Folgenden nun als kleines Beispiel das Zonenfile vom Bind für kernel-error.com mit den gesetzten Records.

$ORIGIN .
$TTL 86400      ; 1 day
kernel-error.com             IN SOA ns1.kernel-error.de. root.kernel-error.de. (
                                2014010101 ; serial
                                15000      ; refresh
                                1800       ; retry (30 minutes)
                                604800     ; expire (4 weeks)
                                86400      ; minimum (1 day)
                                )
                        NS      ns1.kernel-error.de.
                        NS      ns2.kernel-error.org.

$TTL 1H
						IN TXT "MS=ms12345678"
						IN TXT "v=spf1 include:spf.protection.outlook.com -all"
						
						IN MX	0 kernel-error-com0i.mail.protection.outlook.com.
						
_sip._tls.kernel-error.com.			IN SRV   1 100 443	sipdir.online.lync.com.
_sipfederationtls._tcp.kernel-error.com.	IN SRV   1 100 5061	sipfed.online.lync.com.


$ORIGIN kernel-error.com

$TTL 1H
autodiscover		IN CNAME	autodiscover.outlook.com.
sip			IN CNAME	sipdir.online.lync.com.
lyncdiscover		IN CNAME	webdir.online.lync.com.
msoid			IN CNAME	clientconfig.microsoftonline-p.net.

Prüfen lassen sich alle gesetzten DNS-RECORDS natürlich wie immer schnell mit dig!

TXT     @     v=spf1 include:spf.protection.outlook.com -all     1 Stunde

$ dig +nocmd +noall +answer kernel-error.com IN TXT @ns1.kernel-error.de
kernel-error.com.            3600    IN      TXT     "MS=ms12345678"
kernel-error.com.            3600    IN      TXT     "v=spf1 include:spf.protection.outlook.com -all"

MX     0     @     kernel-error-com01.mail.protection.outlook.com     1 Stunde

$ dig +nocmd +noall +answer kernel-error.com IN MX @ns1.kernel-error.de
kernel-error.com.            3600    IN      MX      0 kernel-error-com0i.mail.protection.outlook.com.

SRV     _sip     _tls     443     1     100     1 Stunde     kernel-error.com     sipdir.online.lync.com

$ dig +nocmd +noall +answer _sip._tls.kernel-error.com. IN SRV @ns1.kernel-error.de
_sip._tls.kernel-error.com.  3600    IN      SRV     1 100 443 sipdir.online.lync.com.

SRV     _sipfederationtls     _tcp     5061     1     100     1 Stunde     kernel-error.com     sipfed.online.lync.com

$ dig +nocmd +noall +answer _sipfederationtls._tcp.kernel-error.com. IN SRV @ns1.kernel-error.de
_sipfederationtls._tcp.kernel-error.com. 3600 IN SRV 1 100 5061 sipfed.online.lync.com.

CNAME     –     autodiscover     autodiscover.outlook.com     1 Stunde

$ dig +nocmd +noall +answer autodiscover.kernel-error.com IN A @ns1.kernel-error.de
autodiscover.kernel-error.com. 3600  IN      CNAME   autodiscover.outlook.com.

CNAME     sip.kernel-error.com     sipdir.online.lync.com     1 Stunde

$ dig +nocmd +noall +answer sip.kernel-error.com IN A @ns1.kernel-error.de
sip.kernel-error.com.        3600    IN      CNAME   sipdir.online.lync.com.

CNAME     lyncdiscover.kernel-error.com     webdir.online.lync.com     1 Stunde

$ dig +nocmd +noall +answer lyncdiscover.kernel-error.com IN A @ns1.kernel-error.de
lyncdiscover.kernel-error.com. 3600  IN      CNAME   webdir.online.lync.com.

CNAME     msoid.kernel-error.com     clientconfig.microsoftonline-p.net     1 Stunde

$ dig +nocmd +noall +answer msoid.kernel-error.com IN A @ns1.kernel-error.de
msoid.kernel-error.com.      3600    IN      CNAME   clientconfig.microsoftonline-p.net.

Noch Fragen? Dann fragen 🙂 Sonst wünsche ich noch „viel Spaß“ mit dem neuen Microsoft Online Produkten….

iX – Webhosting-Umfrage mit Verlosung

Die iX feiert bald das 25-jährige Jubiläum. Um den Lesern etwas Gutes zu tun möglichst viele darauf aufmerksam zu machen und um ein paar statistische Daten für die kommende Ausgabe zu sammeln, gibt es eine Verlosung mit tollen Preisen.

Wenn also jemand einen Preis gewinnen möchte der iX bei ihrer Datensammlung helfen möchte, folge dieser bitte einfach dem nun folgenden Link: https://umfrage.heise.de/limesurvey/index.php/55238/lang-de

Damit die Gewinner benachrichtigt werden können, muss neben der E-Mail Adresse und dem Namen selbstverständlich ebenfalls die volle Adresse angegeben werden. Na ja, zumindest werden die Daten per TLS übertragen! tongue-out

Bin ich heute wieder zu böse?

Google schaut in die E-Mails seiner gmail Nutzer!

Google schaut in die E-Mails seiner gmail Nutzer, wertet den Inhalt aus und zeigt dem Nutzer dann maßgeschneiderte Werbung…. OK, ist jetzt nichts Neues! Nun hat Google aber bekanntgegeben dass sie zumindest keine Schüler mehr in dieser Form abschnorcheln will.

Zu lesen ist es hier: http://googleenterprise.blogspot.de/2014/04/protecting-students-with-google-apps.html

Toll, oder? Super… Alle freuen sich… O_o ALLE FREUEN SICH! Leute, schlaft ihr alle? Google durchsucht, nach eigenen Angaben, keine E-Mail Accounts von Schülern mehr und SCHÜTZT sie somit vor Werbung welche zu E-Mail Inhalten passt!!!!!

Das ist so als wenn der Postbote die Briefe liest und immer direkt das passende Werbeprospekt beilegt. Warum freuen sich alle? Ich verstehe es nicht, tut mir leid!

AOL macht jetzt auch Mailinglisten „kaputt“ / DMARC

Das gefällt mir laughing… Nachdem nun Yahoo die Eier hatte einfach mal ihre DMARC Policy „scharf“ (reject) zu schalten und sich so viel Schimpfe von aller Welt dafür eingesammelt hat und beschuldigt wurde die Mailinglisten „kaputt“ zu machen…. Tja, da zieht AOL nun in gewisser Weise nach: http://postmaster-blog.aol.com/2014/04/22/aol-mail-updates-dmarc-policy-to-reject/

AOL hat nämlich gerade ein tierisches Spam-Problem. Also jetzt nicht direkt, eher haben andere das Problem, es betrifft AOL nur in soweit das deren Absenderdomain dafür missbraucht wird. Die Spam E-Mails sehen also so aus als wenn sie von AOL kommen. AOL hat nun also ihre DMARC Policy scharf geschaltet um das Problem damit etwas eindämmen zu können. Ob nun wohl so langsam Google und Microsoft ebenfalls nachziehen? Inzwischen sollten die Admins der Mailinglisten ja schon mal „warm“ gelaufen sein tongue-out

Mailgraph: Erweiterung der Grafiken um SPF, DMARC und DKIM

Zu allem Monitoring sind grafische Auswertungen eine feine Sache um auf einen kurzen Blick zu erkennen ob sich etwas „positiv“ oder eher „negativ“ entwickelt. Eine sehr simple Lösung ist dabei mailgraph von David Schweikert. Um kleinere Mailserver im Auge zu behalten oder Änderungen an Testsystemen zu bewundern setzte ich es gerne ein.

Als ich mich vor einiger Zeit mit SPF / DKIM und DMARC beschäftigt habe, interessiere mich natürlich wie viele der E-Mails im Schnitt signiert sind, wie oft ein Test fehlschlägt und somit vermeintliche Werbung abgewehrt hat usw. usw… Ich habe mir dann zu beginn die Maillogs per egrep vorgenommen. Reichte für eine erste Übersicht. Irgendwann wollte ich mehr und habe begonnen mir mailgraph (Version 1.14) so zu erweitern das er mir genau diese Informationen anzeigt. Ich habe zwar einen spf-patch für mailgraph gefunden, nur wollte ich ja noch mehr.

Vor kurzem habe ich einen kleinen Vortrag zum Thema DMARC gehalten und dabei die Graphen auf einem der Testsysteme gezeigt. Da es ungewöhnlich viele Rückfragen dazu gab (wie, woher…) habe ich versprochen die Erweiterung online zu stellen!

Auf einem normalen Debian System müssen nur die beiden Dateien /usr/sbin/mailgraph sowie /usr/lib/cgi-bin/mailgraph.cgi durch die folgenden ersetzt werden. Wie immer bitte selbst denkend und nach vorheriger Sicherung tongue-out. Davon abgesehen das ich kein Programmierer bin, nehme ich Verbesserungsvorschläge sehr gerne an!

Dabei ist es ausgelegt für Postfix mit postfix-policyd-spf, opendkim und opendmarc

Beispiel…

Hier die bekannte Grafik der insg. empfangenen und versendeten E-Mails aus der letzten Woche.

Direkt gefolgt von der grafischen Auswertung der zurückgewiesenen, verseuchten usw… Mails.

Der folgende Graph zeigt den Anteil der E-Mails bei denen es keinen SPF Schutz der Domain gibt (SPF none), der SPF Check fehlgeschlagen ist (SPF fail) und selbstverständlich wo der SPF Check erfolgreich (SPF pass) war.

Gleiches gilt für den folgenden Graphen, wobei es sich hier auf DMARC bezieht.

Zu guter Letzte der Graph zu DKIM.


Download

Ich habe dafür zwei Patchfiles erstellt und diese lassen sich hier herunterladen: mailgraph-dmarc-spf-dkim.patch.tar.gz

/usr/sbin/mailgraph.patch

*** mailgraph	2012-06-17 00:00:00.000000000 +0200
--- mailgraph	2014-04-24 08:59:58.964977886 +0200
***************
*** 4,9 ****
--- 4,10 ----
  # copyright (c) 2000-2007 ETH Zurich
  # copyright (c) 2000-2007 David Schweikert <david@schweikert.ch>
  # released under the GNU General Public License
+ # with dkim-, dmarc, spf-patch Sebastian van de Meer <kernel-error@kernel-error.de>
  
  ######## Parse::Syslog 1.09 (automatically embedded) ########
  package Parse::Syslog;
***************
*** 382,388 ****
  my $rrd_greylist = "mailgraph_greylist.rrd";
  my $year;
  my $this_minute;
! my %sum = ( sent => 0, received => 0, bounced => 0, rejected => 0, virus => 0, spam => 0, greylisted => 0, delayed => 0);
  my $rrd_inited=0;
  
  my %opt = ();
--- 383,389 ----
  my $rrd_greylist = "mailgraph_greylist.rrd";
  my $year;
  my $this_minute;
! my %sum = ( sent => 0, received => 0, bounced => 0, rejected => 0, spfnone => 0, spffail => 0, spfpass => 0, dmarcnone => 0, dmarcfail => 0, dmarcpass => 0, dkimnone => 0, dkimfail => 0, dkimpass => 0, virus => 0, spam => 0, greylisted => 0, delayed => 0);
  my $rrd_inited=0;
  
  my %opt = ();
***************
*** 396,401 ****
--- 397,411 ----
  sub event_rejected($);
  sub event_virus($);
  sub event_spam($);
+ sub event_spfnone($);
+ sub event_spffail($);
+ sub event_spfpass($);
+ sub event_dmarcnone($);
+ sub event_dmarcfail($);
+ sub event_dmarcpass($);
+ sub event_dkimnone($);
+ sub event_dkimfail($);
+ sub event_dkimpass($);
  sub event_greylisted($);
  sub event_delayed($);
  sub init_rrd($);
***************
*** 533,538 ****
--- 543,557 ----
  				'DS:recv:ABSOLUTE:'.($rrdstep*2).':0:U',
  				'DS:bounced:ABSOLUTE:'.($rrdstep*2).':0:U',
  				'DS:rejected:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:spfnone:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:spffail:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:spfpass:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:dmarcnone:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:dmarcfail:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:dmarcpass:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:dkimnone:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:dkimfail:ABSOLUTE:'.($rrdstep*2).':0:U',
+ 				'DS:dkimpass:ABSOLUTE:'.($rrdstep*2).':0:U',
  				"RRA:AVERAGE:0.5:$day_steps:$realrows",   # day
  				"RRA:AVERAGE:0.5:$week_steps:$realrows",  # week
  				"RRA:AVERAGE:0.5:$month_steps:$realrows", # month
***************
*** 614,619 ****
--- 633,649 ----
  				event($time, 'bounced');
  			}
  		}
+ 	  elsif ($prog eq 'policy-spf') {
+ 	    if ($text =~ /Received-SPF: none/) {
+ 	      event($time, 'spfnone');
+ 	    }
+ 	    elsif($text =~ /Received-SPF: pass/) {
+ 				event($time, 'spfpass');
+ 			}
+ 	    elsif($text =~ /Received-SPF:/) {
+ 				event($time, 'spffail');
+ 			}
+ 	  }
  		elsif($prog eq 'local') {
  			if($text =~ /\bstatus=bounced\b/) {
  				event($time, 'bounced');
***************
*** 862,867 ****
--- 892,919 ----
  			event($time, 'virus');
  		}
  	}
+ 	elsif ($prog eq 'opendmarc') {
+ 		if ($text =~ /pass/) {
+ 			event($time, 'dmarcpass');
+ 		}
+ 		elsif($text =~ /none/) {
+ 			event($time, 'dmarcnone');
+ 		}
+ 		elsif($text =~ /fail/) {
+ 			event($time, 'dmarcfail');
+ 		}
+ 	}
+ 	elsif ($prog eq 'opendkim') {
+ 		if ($text =~ /DKIM verification successful/) {
+ 			event($time, 'dkimpass');
+ 		}
+ 		elsif($text =~ /no signature data/) {
+ 			event($time, 'dkimnone');
+ 		}
+ 		elsif($text =~ /bad signature data/) {
+ 			event($time, 'dkimfail');
+ 		}
+ 	}	
  	elsif($prog eq 'avmilter') {
  		# AntiVir Milter
  		if($text =~ /^Alert!/) {
***************
*** 918,931 ****
  	return 1 if $m == $this_minute;
  	return 0 if $m < $this_minute;
  
! 	print "update $this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{virus}:$sum{spam}:$sum{greylisted}:$sum{delayed}\n" if $opt{verbose};
! 	RRDs::update $rrd, "$this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}" unless $opt{'no-mail-rrd'};
  	RRDs::update $rrd_virus, "$this_minute:$sum{virus}:$sum{spam}" unless $opt{'no-virus-rrd'};
  	RRDs::update $rrd_greylist, "$this_minute:$sum{greylisted}:$sum{delayed}" unless $opt{'no-greylist-rrd'};
  	if($m > $this_minute+$rrdstep) {
  		for(my $sm=$this_minute+$rrdstep;$sm<$m;$sm+=$rrdstep) {
! 			print "update $sm:0:0:0:0:0:0:0:0 (SKIP)\n" if $opt{verbose};
! 			RRDs::update $rrd, "$sm:0:0:0:0" unless $opt{'no-mail-rrd'};
  			RRDs::update $rrd_virus, "$sm:0:0" unless $opt{'no-virus-rrd'};
  			RRDs::update $rrd_greylist, "$sm:0:0" unless $opt{'no-greylist-rrd'};
  		}
--- 970,983 ----
  	return 1 if $m == $this_minute;
  	return 0 if $m < $this_minute;
  
! 	print "update $this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{spfnone}:$sum{spffail}:$sum{spfpass}:$sum{dmarcnone}:$sum{dmarcfail}:$sum{dmarcpass}:$sum{dkimnone}:$sum{dkimfail}:$sum{dkimpass}:$sum{virus}:$sum{spam}:$sum{greylisted}:$sum{delayed}\n" if $opt{verbose};
! 	RRDs::update $rrd, "$this_minute:$sum{sent}:$sum{received}:$sum{bounced}:$sum{rejected}:$sum{spfnone}:$sum{spffail}:$sum{spfpass}:$sum{dmarcnone}:$sum{dmarcfail}:$sum{dmarcpass}:$sum{dkimnone}:$sum{dkimfail}:$sum{dkimpass}" unless $opt{'no-mail-rrd'};
  	RRDs::update $rrd_virus, "$this_minute:$sum{virus}:$sum{spam}" unless $opt{'no-virus-rrd'};
  	RRDs::update $rrd_greylist, "$this_minute:$sum{greylisted}:$sum{delayed}" unless $opt{'no-greylist-rrd'};
  	if($m > $this_minute+$rrdstep) {
  		for(my $sm=$this_minute+$rrdstep;$sm<$m;$sm+=$rrdstep) {
! 			print "update $sm:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 (SKIP)\n" if $opt{verbose};
! 			RRDs::update $rrd, "$sm:0:0:0:0:0:0:0:0:0:0:0:0:0" unless $opt{'no-mail-rrd'};
  			RRDs::update $rrd_virus, "$sm:0:0" unless $opt{'no-virus-rrd'};
  			RRDs::update $rrd_greylist, "$sm:0:0" unless $opt{'no-greylist-rrd'};
  		}
***************
*** 935,940 ****
--- 987,1001 ----
  	$sum{received}=0;
  	$sum{bounced}=0;
  	$sum{rejected}=0;
+ 	$sum{spfnone}=0;
+ 	$sum{spffail}=0;
+ 	$sum{spfpass}=0;
+ 	$sum{dmarcnone}=0;
+ 	$sum{dmarcfail}=0;
+ 	$sum{dmarcpass}=0;
+ 	$sum{dkimnone}=0;
+ 	$sum{dkimfail}=0;
+ 	$sum{dkimpass}=0;
  	$sum{virus}=0;
  	$sum{spam}=0;
  	$sum{greylisted}=0;

/usr/lib/cgi-bin/mailgraph.cgi.patch

*** mailgraph.cgi	2012-06-17 00:00:00.000000000 +0200
--- mailgraph.cgi	2014-04-24 09:03:11.917988368 +0200
***************
*** 4,9 ****
--- 4,10 ----
  # copyright (c) 2000-2007 ETH Zurich
  # copyright (c) 2000-2007 David Schweikert <david@schweikert.ch>
  # released under the GNU General Public License
+ # with dkim-, dmarc, spf-patch Sebastian van de Meer <kernel-error@kernel-error.de>
  
  use RRDs;
  use POSIX qw(uname);
***************
*** 15,21 ****
--- 16,25 ----
  my $xpoints = 540;
  my $points_per_sample = 3;
  my $ypoints = 160;
+ my $ypoints_spf = 96;
  my $ypoints_err = 96;
+ my $ypoints_dmarc = 96;
+ my $ypoints_dkim = 96;
  my $ypoints_grey = 96;
  my $rrd = '/var/lib/mailgraph/mailgraph.rrd'; # path to where the RRD database is
  my $rrd_virus = '/var/lib/mailgraph/mailgraph_virus.rrd'; # path to where the Virus RRD database is
***************
*** 32,37 ****
--- 36,50 ----
  	sent       => '000099', # rrggbb in hex
  	received   => '009900',
  	rejected   => 'AA0000',
+ 	spfnone    => '000AAA',
+ 	spffail    => '12FF0A',
+ 	spfpass    => 'D15400',
+ 	dmarcnone  => 'FFFF00',
+ 	dmarcfail  => 'FF00EA',
+ 	dmarcpass  => '00FFD5',
+ 	dkimnone   => '3013EC',
+ 	dkimfail   => '006B3A',
+ 	dkimpass   => '491503',
  	bounced    => '000000',
  	virus      => 'DDBB00',
  	spam       => '999999',
***************
*** 154,159 ****
--- 167,292 ----
  	);
  }
  
+ sub graph_spf($)
+ {
+ 	my ($range, $file) = @_;
+ 	my $step = $range*$points_per_sample/$xpoints;
+ 	rrd_graph($range, $file, $ypoints_spf,
+ 		"DEF:spfpass=$rrd:spfpass:AVERAGE",
+ 		"DEF:mspfpass=$rrd:spfpass:MAX",
+ 		"CDEF:rspfpass=spfpass,60,*",
+ 		"CDEF:dspfpass=spfpass,UN,0,spfpass,IF,$step,*",
+ 		"CDEF:sspfpass=PREV,UN,dspfpass,PREV,IF,dspfpass,+",
+ 		"CDEF:rmspfpass=mspfpass,60,*",
+ 		"AREA:rspfpass#$color{spfpass}:SPF pass",
+ 		'GPRINT:sspfpass:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rspfpass:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmspfpass:MAX:max\: %4.0lf msgs/min\l',
+ 	
+ 		"DEF:spfnone=$rrd:spfnone:AVERAGE",
+ 		"DEF:mspfnone=$rrd:spfnone:MAX",
+ 		"CDEF:rspfnone=spfnone,60,*",
+ 		"CDEF:dspfnone=spfnone,UN,0,spfnone,IF,$step,*",
+ 		"CDEF:sspfnone=PREV,UN,dspfnone,PREV,IF,dspfnone,+",
+ 		"CDEF:rmspfnone=mspfnone,60,*",
+ 		"STACK:rspfnone#$color{spfnone}:SPF none",
+ 		'GPRINT:sspfnone:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rspfnone:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmspfnone:MAX:max\: %4.0lf msgs/min\l',
+ 
+ 		"DEF:spffail=$rrd:spffail:AVERAGE",
+ 		"DEF:mspffail=$rrd:spffail:MAX",
+ 		"CDEF:rspffail=spffail,60,*",
+ 		"CDEF:dspffail=spffail,UN,0,spffail,IF,$step,*",
+ 		"CDEF:sspffail=PREV,UN,dspffail,PREV,IF,dspffail,+",
+ 		"CDEF:rmspffail=mspffail,60,*",
+ 		"LINE2:rspffail#$color{spffail}:SPF fail",
+ 		'GPRINT:sspffail:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rspffail:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmspffail:MAX:max\: %4.0lf msgs/min\l',
+ 	);
+ }
+ 
+ sub graph_dmarc($)
+ {
+ 	my ($range, $file) = @_;
+ 	my $step = $range*$points_per_sample/$xpoints;
+ 	rrd_graph($range, $file, $ypoints_dmarc,
+ 		"DEF:dmarcpass=$rrd:dmarcpass:AVERAGE",
+ 		"DEF:mdmarcpass=$rrd:dmarcpass:MAX",
+ 		"CDEF:rdmarcpass=dmarcpass,60,*",
+ 		"CDEF:ddmarcpass=dmarcpass,UN,0,dmarcpass,IF,$step,*",
+ 		"CDEF:sdmarcpass=PREV,UN,ddmarcpass,PREV,IF,ddmarcpass,+",
+ 		"CDEF:rmdmarcpass=mdmarcpass,60,*",
+ 		"AREA:rdmarcpass#$color{dmarcpass}:DMARC pass",
+ 		'GPRINT:sdmarcpass:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rdmarcpass:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmdmarcpass:MAX:max\: %4.0lf msgs/min\l',
+ 		
+ 		"DEF:dmarcnone=$rrd:dmarcnone:AVERAGE",
+ 		"DEF:mdmarcnone=$rrd:dmarcnone:MAX",
+ 		"CDEF:rdmarcnone=dmarcnone,60,*",
+ 		"CDEF:ddmarcnone=dmarcnone,UN,0,dmarcnone,IF,$step,*",
+ 		"CDEF:sdmarcnone=PREV,UN,ddmarcnone,PREV,IF,ddmarcnone,+",
+ 		"CDEF:rmdmarcnone=mdmarcnone,60,*",
+ 		"STACK:rdmarcnone#$color{dmarcnone}:DMARC none",
+ 		'GPRINT:sdmarcnone:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rdmarcnone:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmdmarcnone:MAX:max\: %4.0lf msgs/min\l',
+ 
+ 		"DEF:dmarcfail=$rrd:dmarcfail:AVERAGE",
+ 		"DEF:mdmarcfail=$rrd:dmarcfail:MAX",
+ 		"CDEF:rdmarcfail=dmarcfail,60,*",
+ 		"CDEF:ddmarcfail=dmarcfail,UN,0,dmarcfail,IF,$step,*",
+ 		"CDEF:sdmarcfail=PREV,UN,ddmarcfail,PREV,IF,ddmarcfail,+",
+ 		"CDEF:rmdmarcfail=mdmarcfail,60,*",
+ 		"LINE2:rdmarcfail#$color{dmarcfail}:DMARC fail",
+ 		'GPRINT:sdmarcfail:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rdmarcfail:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmdmarcfail:MAX:max\: %4.0lf msgs/min\l',
+ 	);
+ }
+ 
+ sub graph_dkim($)
+ {
+ 	my ($range, $file) = @_;
+ 	my $step = $range*$points_per_sample/$xpoints;
+ 	rrd_graph($range, $file, $ypoints_dkim,
+ 		"DEF:dkimpass=$rrd:dkimpass:AVERAGE",
+ 		"DEF:mdkimpass=$rrd:dkimpass:MAX",
+ 		"CDEF:rdkimpass=dkimpass,60,*",
+ 		"CDEF:ddkimpass=dkimpass,UN,0,dkimpass,IF,$step,*",
+ 		"CDEF:sdkimpass=PREV,UN,ddkimpass,PREV,IF,ddkimpass,+",
+ 		"CDEF:rmdkimpass=mdkimpass,60,*",
+ 		"AREA:rdkimpass#$color{dkimpass}:DKIM pass",
+ 		'GPRINT:sdkimpass:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rdkimpass:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmdkimpass:MAX:max\: %4.0lf msgs/min\l',
+ 		
+ 		"DEF:dkimnone=$rrd:dkimnone:AVERAGE",
+ 		"DEF:mdkimnone=$rrd:dkimnone:MAX",
+ 		"CDEF:rdkimnone=dkimnone,60,*",
+ 		"CDEF:ddkimnone=dkimnone,UN,0,dkimnone,IF,$step,*",
+ 		"CDEF:sdkimnone=PREV,UN,ddkimnone,PREV,IF,ddkimnone,+",
+ 		"CDEF:rmdkimnone=mdkimnone,60,*",
+ 		"STACK:rdkimnone#$color{dkimnone}:DKIM none",
+ 		'GPRINT:sdkimnone:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rdkimnone:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmdkimnone:MAX:max\: %4.0lf msgs/min\l',
+ 
+ 		"DEF:dkimfail=$rrd:dkimfail:AVERAGE",
+ 		"DEF:mdkimfail=$rrd:dkimfail:MAX",
+ 		"CDEF:rdkimfail=dkimfail,60,*",
+ 		"CDEF:ddkimfail=dkimfail,UN,0,dkimfail,IF,$step,*",
+ 		"CDEF:sdkimfail=PREV,UN,ddkimfail,PREV,IF,ddkimfail,+",
+ 		"CDEF:rmdkimfail=mdkimfail,60,*",
+ 		"LINE2:rdkimfail#$color{dkimfail}:DKIM fail",
+ 		'GPRINT:sdkimfail:MAX:total\: %8.0lf msgs',
+ 		'GPRINT:rdkimfail:AVERAGE:avg\: %5.2lf msgs/min',
+ 		'GPRINT:rmdkimfail:MAX:max\: %4.0lf msgs/min\l',
+ 	);
+ }
+ 
  sub graph_grey($)
  {
  	my ($range, $file) = @_;
***************
*** 235,240 ****
--- 368,376 ----
  		print "<h2 id=\"G$n\">$graphs[$n]{title}</h2>\n";
  		print "<p><img src=\"$scriptname?${n}-n\" alt=\"mailgraph\"/><br/>\n";
  		print "<img src=\"$scriptname?${n}-e\" alt=\"mailgraph\"/></p>\n";
+ 		print "<img src=\"$scriptname?${n}-s\" alt=\"mailgraph\"/></p>\n";
+ 		print "<img src=\"$scriptname?${n}-d\" alt=\"mailgraph\"/></p>\n";
+ 		print "<img src=\"$scriptname?${n}-k\" alt=\"mailgraph\"/></p>\n";
  		print "<img src=\"$scriptname?${n}-g\" alt=\"mailgraph\"/></p>\n";
  	}
  
***************
*** 285,290 ****
--- 421,441 ----
  			graph_err($graphs[$1]{seconds}, $file);
  			send_image($file);
  		}
+ 		elsif($img =~ /^(\d+)-s$/) {
+ 			my $file = "$tmp_dir/$uri/mailgraph_$1_spf.png";
+ 			graph_spf($graphs[$1]{seconds}, $file);
+ 			send_image($file);
+ 		}
+ 		elsif($img =~ /^(\d+)-d$/) {
+ 			my $file = "$tmp_dir/$uri/mailgraph_$1_dmarc.png";
+ 			graph_dmarc($graphs[$1]{seconds}, $file);
+ 			send_image($file);
+ 		}
+ 		elsif($img =~ /^(\d+)-k$/) {
+ 			my $file = "$tmp_dir/$uri/mailgraph_$1_dkim.png";
+ 			graph_dkim($graphs[$1]{seconds}, $file);
+ 			send_image($file);
+ 		}
  		elsif($img =~ /^(\d+)-g$/) {
  			my $file = "$tmp_dir/$uri/mailgraph_$1_grey.png";
  			graph_grey($graphs[$1]{seconds}, $file);

Bei Fragen… Wie immer Fragen 🙂


09-08-2014 Update

Ich habe noch einen Patch erstellt um die Auswertung von DNSSEC DANE im Zusammenhang mit Postfix zu visualisieren. Dieses findet sich hier: mailgraph Graphen um DANE erweitern

Bei Interesse erstelle ich vielleicht noch einen großen Patch, welcher beides beinhaltet.

systemd und ntp

Man ist das hässlich… Da sitze ich hier an einem Sabayon System und bekomme keine saubere Uhrzeit. Zwar sollte ntpd.service beim Start die Uhrzeit abgleichen.. Der Dienst verkackt aber seinen Starten, weil er „noch“ kein Netzwerk hat. Dabei ist sogar hinterlegt dass es er erst nach dem Netzwerkmanager startet, denn noch scheint der Netzwerkmanager so schnell keine Verbindung zu bekommen. Der initiale Abgleich vom ntpd.service schlägt daher fehlt, der Dienst bleibt aus und es probiert es auch später nicht mehr. Grütze..

$ systemctl --failed
UNIT            LOAD   ACTIVE SUB    DESCRIPTION
ntpdate.service loaded failed failed Set time via NTP using ntpdate

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

1 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

Ich lasse jetzt mal das Bughunting und setzte einfach auf chrony 😀 Nur für Zeitsync ist das ok für mich!

$ equo search chrony
╠  @@ Suche...
╠      @@ Paket: net-misc/chrony-1.29.1 Branch: 5, [sabayonlinux.org] 
╠          Verfügbar:      Version: 1.29.1 ~ tag: NoTag ~ Version: 0
╠          Installiert:    Version: Nicht installiert ~ tag: n/a ~ Version: n/a
╠          Slot:           0
╠          Homepage:       http://chrony.tuxfamily.org/ 
╠          Beschreibung:   NTP client and server programs 
╠          Lizenz:         GPL-2
╠   Schlüsselwörter:  chrony
╠   Gefunden:         1 Eintrag

Gefunde und dann  installieren….

$ equo install chrony
╠  @@ Berechne Abhängigkeiten...
╠  ## [N] [sabayonlinux.org] dev-libs/libedit-20130712.3.1|0
╠  ## [N] [sabayonlinux.org] net-misc/chrony-1.29.1|0
╠  @@ Pakete die installiert/aktualisiert/entfernt werden müssen: 2
╠  @@ Pakete die entfernt werden müssen: 0
╠  @@ Download Größe: 413.1kB
╠  @@ Benutzter Festplattenspeicher: 715.6kB
╠  @@ Du brauchst zumindest: 1.5MB freien Speicherplatz
╠  ::: >>>  (1/1) 2 Pakete
╠    ## downloaden: 2 Pakete
╠    ## ( mirror #1 ) [dev-libs:libedit-20130712.3.1.3556f679066ec7d787573f08ac74ef24922243b2~0.tbz2] @ http://na.mirror.garr.it
╠    ## ( mirror #1 ) [net-misc:chrony-1.29.1.98ee02f66d56c49e1fdc4d713b2cea5ff23d775e~0.tbz2] @ http://na.mirror.garr.it
╠   ## Sammeldownload: 2 Artikel
╠    # [1] na.mirror.garr.it => dev-libs:libedit-20130712.3.1.3556f679066ec7d787573f08ac74ef24922243b2~0.tbz2
╠    # [2] na.mirror.garr.it => net-misc:chrony-1.29.1.98ee02f66d56c49e1fdc4d713b2cea5ff23d775e~0.tbz2
╠    ## Überprüfe Paketprüfsumme...
╠    ## Überprüfe Paketprüfsumme...
╠       : [net-misc:chrony-1.29.1.98ee02f66d56c49e1fdc4d713b2cea5ff23d775e~0.tbz2] GPG validated
╠       : [dev-libs:libedit-20130712.3.1.3556f679066ec7d787573f08ac74ef24922243b2~0.tbz2] GPG validated
╠       : [net-misc:chrony-1.29.1.98ee02f66d56c49e1fdc4d713b2cea5ff23d775e~0.tbz2] SHA1 validated
╠       : SHA256 deaktiviert
╠       : [dev-libs:libedit-20130712.3.1.3556f679066ec7d787573f08ac74ef24922243b2~0.tbz2] SHA1 validated
╠       : SHA512 deaktiviert
╠       : SHA256 deaktiviert
╠       : SHA512 deaktiviert
╠    ## ( mirror #1 ) [dev-libs:libedit-20130712.3.1.3556f679066ec7d787573f08ac74ef24922243b2~0.tbz2] erfolgreich @ http://na.mirror.garr.it
╠    ## ( mirror #1 ) [net-misc:chrony-1.29.1.98ee02f66d56c49e1fdc4d713b2cea5ff23d775e~0.tbz2] erfolgreich @ http://na.mirror.garr.it
╠    ##  angehäufte Transferrate: 658.3kB/Sekunde
╠  +++ >>>  (1/2) dev-libs/libedit-20130712.3.1
╠    ## Entpacke: dev-libs:libedit-20130712.3.1.3556f679066ec7d787573f08ac74ef24922243b2~0.tbz2
╠    ## Installiere Paket: dev-libs/libedit-20130712.3.1
╠    ## [BSD replacement for libreadline.]
╠    ## Updating installed packages repository: dev-libs/libedit-20130712.3.1
>>> Regenerating /etc/ld.so.cache...
╠    ## Aufräumen: dev-libs/libedit-20130712.3.1
╠  +++ >>>  (2/2) net-misc/chrony-1.29.1
╠    ## Entpacke: net-misc:chrony-1.29.1.98ee02f66d56c49e1fdc4d713b2cea5ff23d775e~0.tbz2
╠    ## Installiere Paket: net-misc/chrony-1.29.1
╠    ## [NTP client and server programs]
╠    ## Updating installed packages repository: net-misc/chrony-1.29.1
╠    ## Aufräumen: net-misc/chrony-1.29.1
╠  @@ Installation vollständig.
╠  @@ No configuration files to update.

Beim Boot soll er in Zukunft gestartet werden!

$ systemctl enable chronyd.service
ln -s '/usr/lib64/systemd/system/chronyd.service' '/etc/systemd/system/multi-user.target.wants/chronyd.service'

Och ja, am besten sollte der Dienst direkt gestartet werde…

$ systemctl start chronyd.service

Bevor ich es vergesse, den hässlichen ntpd.service will ich beim Start nicht mehr sehen!

$ systemctl disable ntpd.service

DMARC Milter und Postfix auf Debian 7 Wheezy

Über DMARC selbst habe ich ja schon etwas geschrieben. Selbst eine DMARC Policy zu veröffentlichen und sich um die eingehenden Reports zu kümmern ebenfalls. Heute soll es nun darum gehen, mit seinem Postfix auf einem Debian 7 die DMARC Policys der Absender zu Prüfen und zu berücksichtigen.

Es gibt bereits einen fertigen Milter für DMARC. Dieser findet sich leider nicht im aktuellen stable Zweig eines Debian 7.4 Wheezy. Nun könnte man auf einen Backport zurückgreifen…. So etwas kann einem aber schon mal das System etwas mehr „umdrehen“ als man wirklich möchte. Nur für den openDMARC Milter ist das nicht nötig.

Die Installation ist sehr einfach und im folgenden beschrieben. Dabei gehe ich von einem funktionsfähigen Postfix, SPF und DKIM Filter aus. Für dieses Setup setzte ich auf postgrey sowie  postfix-policyd-spf-perl. Denn der openDMARC Milter „verlässt“ sich darauf, das diese Programme bereits die richtigen Informationen in die Mailheader geschrieben haben.

ACHTUNG
Wer zum Beispiel AMaViS als smtpd_proxy_filter einsetzte, wird feststellen dass es nie zum openDMARC Milter kommt. Das liegt daran, dass die Milter an einer Stelle kommen, an welcher die E-Mail nie mehr vorbei kommt, wenn sie einmal durch einen smtpd_proxy_filter gelaufen sind. Hier kann man nun also abwarten bis DMARC nicht mehr als Milter arbeitet oder AMaViS als content_filter einsetzten tongue-out.

Wie immer ist es eine Beschreibung die den Einstieg erleichtern soll und keine „so ist es perfekt“ Beschreibung. Nun also los…

Zuerst den openDMARC Milter direkt von der Projektseite herunterladen.

http://sourceforge.net/projects/opendmarc/

Für das spätere Kompilieren braucht man in jedem Fall die Entwicklerpakete für libmilter, daher installiere ich sie zuerst.

$ apt-get install libmilter-dev

Dann packen wir mal den Download aus..

$ tar xvzf opendmarc-1.2.0.tar.gz

Ins Verzeichnis wechseln und wie gewohnt kompilieren. Ich setzte dabei einfach mal das Prefix auf /usr, damit am Ende nicht alles unter /usr/local/ liegt. Bitte selbstdenkend nachmachen 🙂

$ ./configure --prefix=/usr
$ make && make install

Der Milter sollte aus Sicherheitsgründen nicht als root laufen, daher lege ich dafür einen Benutzer opendmarc an und lege seine Heimat direkt ins spätere „Arbeitsverzeichnis“. Als zweites werden die Rechte gesetzt, damit der Benutzer in seinem Zuhause arbeiten kann.

$ adduser --quiet --system --group --home /var/run/opendmarc opendmarc
$ chown opendmarc:opendmarc /var/run/opendmarc

Man sieht schon, ich versuche mich nahe am Debian Default zu orientieren. Das soll so weiter gehen um spätere Upgrades zu erleichtern und es muss nichts „Neue“ erfunden werden.. Wie im testing Zweig und beim openDKIM Milter wird der zu verwendende Socket/Port… in der Konfigurationsdatei /etc/default/opendmarc gesetzt. Das spätere INIT-Script wird diese Konfigurationsdatei einfach beim Start des Milters, in die eigentliche Konfigurationsdatei, inkludieren. Also:

$ SOCKET="inet:8893@localhost"' > /etc/default/opendmarc

Das INIT-Script greife ich mir aus dem Testing Zweig des kommenden Debian 8…

$ vi /etc/init.d/opendmarc   
#! /bin/sh
#
### BEGIN INIT INFO
# Provides:             opendmarc
# Required-Start:       $syslog $time $local_fs $remote_fs $named $network
# Required-Stop:        $syslog $time $local_fs $remote_fs
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Start the OpenDMARC service
# Description:          Enable DMAR verification and reporting provided by OpenDMARC
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/opendmarc
NAME=opendmarc
DESC="OpenDMARC"
RUNDIR=/var/run/$NAME
USER=opendmarc
GROUP=opendmarc
SOCKET=local:$RUNDIR/$NAME.sock
PIDFILE=$RUNDIR/$NAME.pid

# How long to wait for the process to die on stop/restart
stoptimeout=5

test -x $DAEMON || exit 0

# Include LSB provided init functions
. /lib/lsb/init-functions

# Include opendkim defaults if available
if [ -f /etc/default/opendmarc ] ; then
        . /etc/default/opendmarc
fi

if [ -f /etc/opendmarc.conf ]; then
        CONFIG_SOCKET=`awk '$1 == "Socket" { print $2 }' /etc/opendmarc.conf`
fi

# This can be set via Socket option in config file, so it's not required
if [ -n "$SOCKET" -a -z "$CONFIG_SOCKET" ]; then
        DAEMON_OPTS="-p $SOCKET $DAEMON_OPTS"
fi

DAEMON_OPTS="-c /etc/opendmarc.conf -u $USER -P $PIDFILE $DAEMON_OPTS"

start() {
        # Create the run directory if it doesn't exist
        if [ ! -d "$RUNDIR" ]; then
                install -o "$USER" -g "$GROUP" -m 755 -d "$RUNDIR" || return 2
                [ -x /sbin/restorecon ] && /sbin/restorecon "$RUNDIR"
        fi
        # Clean up stale sockets
        if [ -f "$PIDFILE" ]; then
                pid=`cat $PIDFILE`
                if ! ps -C "$DAEMON" -s "$pid" >/dev/null; then
                        rm "$PIDFILE"
                        TMPSOCKET=""
                        if [ -n "$SOCKET" ]; then
                                TMPSOCKET="$SOCKET"
                        elif [ -n "$CONFIG_SOCKET" ]; then
                                TMPSOCKET="$CONFIG_SOCKET"
                        fi
                        if [ -n "$TMPSOCKET" ]; then
                                # UNIX sockets may be specified with or without the
                                # local: prefix; handle both
                                t=`echo $SOCKET | cut -d: -f1`
                                s=`echo $SOCKET | cut -d: -f2`
                                if [ -e "$s" -a -S "$s" ]; then
                                        if [ "$t" = "$s" -o "$t" = "local" ]; then
                                                rm "$s"
                                        fi
                                fi
                        fi
                fi
        fi
        start-stop-daemon --start --quiet --pidfile "$PIDFILE" --exec "$DAEMON" --test -- $DAEMON_OPTS || return 1
        start-stop-daemon --start --quiet --pidfile "$PIDFILE" --exec "$DAEMON" -- $DAEMON_OPTS || return 2
}

stop() {
        start-stop-daemon --stop --retry "$stoptimeout" --exec "$DAEMON"
        [ "$?" = 2 ] && return 2
}

reload() {
        start-stop-daemon --stop --signal USR1 --exec "$DAEMON"
}

status() {
    local pidfile daemon name status

    pidfile=
    OPTIND=1
    while getopts p: opt ; do
        case "$opt" in
            p)  pidfile="$OPTARG";;
        esac
    done
    shift $(($OPTIND - 1))

    if [ -n "$pidfile" ]; then
        pidfile="-p $pidfile"
    fi
    daemon="$1"
    name="$2"

    status="0"
    pidofproc $pidfile $daemon >/dev/null || status="$?"
    if [ "$status" = 0 ]; then
        log_success_msg "$name is running"
        return 0
    else
        log_failure_msg "$name is not running"
        return $status
    fi
}

case "$1" in
  start)
        echo -n "Starting $DESC: "
        start
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        stop
        echo "$NAME."
        ;;
  restart)
        echo -n "Restarting $DESC: "
        stop
        start
        echo "$NAME."
        ;;
  reload|force-reload)
        echo -n "Restarting $DESC: "
        reload
        echo "$NAME."
        ;;
  status)
        status $DAEMON $NAME
        ;;
  *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
        exit 1
        ;;
esac

exit 0

Dieses nur noch an die richtige Stelle schieben, als ausführbar marken und bei jedem Booten mit starten lassen.

$ cp /pfad/opendmarc /etc/init.d/opendmarc
$ chmod +x /etc/init.d/opendmarc
$ update-rc.d opendmarc defaults

Das war schon fast das Schwerste… Jetzt kopiere ich die mitgelieferte Beispielkonfigurationsdatei für openDMARC nach /etc/.

$ cp /usr/share/doc/opendmarc/opendmarc.conf.sample /etc/

Diese passe ich nun wie folgt an:

$ vi /etc/opendmarc.conf
# This is a basic configuration that can easily be adapted to suit a standard
# installation. For more advanced options, see opendkim.conf(5) and/or
# /usr/share/doc/opendmarc/examples/opendmarc.conf.sample.

##  AuthservID (string)
##      defaults to MTA name
#
AuthservID smtp.kernel-error.de

##  BaseDirectory (string)
##      default (none)
##
##  If set, instructs the filter to change to the specified directory using
##  chdir(2) before doing anything else.  This means any files referenced
##  elsewhere in the configuration file can be specified relative to this
##  directory.  It's also useful for arranging that any crash dumps will be
##  saved to a specific location.
#
# BaseDirectory /var/run/opendmarc

##  ChangeRootDirectory (string)
##      default (none)
##
##  Requests that the operating system change the effective root directory of
##  the process to the one specified here prior to beginning execution.
##  chroot(2) requires superuser access.  A warning will be generated if
##  UserID is not also set.
# 
# ChangeRootDirectory /var/chroot/opendmarc

##  ForensicReports { true | false }
##      default "false"
##
# ForensicReports false

##  IgnoreHosts path
##      default (internal)
##
# IgnoreHosts /usr/local/etc/opendmarc/ignore.hosts

##  IgnoreMailFrom domain[,...]
##      default (none)
##
# IgnoreMailFrom example.com

##  PidFile path
##      default (none)
##
##  Specifies the path to a file that should be created at process start
##  containing the process ID.
##
#
PidFile /var/run/opendmarc.pid

##  RejectFailures { true | false }
##      default "false"
##
RejectFailures false

##  Socket socketspec
##      default (none)
##
##  Specifies the socket that should be established by the filter to receive
##  connections from sendmail(8) in order to provide service.  socketspec is
##  in one of two forms: local:path, which creates a UNIX domain socket at
##  the specified path, or inet:port[@host] or inet6:port[@host] which creates
##  a TCP socket on the specified port for the appropriate protocol family.
##  If the host is not given as either a hostname or an IP address, the
##  socket will be listening on all interfaces.  This option is mandatory
##  either in the configuration file or on the command line.  If an IP
##  address is used, it must be enclosed in square brackets.
#
#Socket inet:8893@localhost

##  SoftwareHeader { true | false }
##      default "false"
##
##  Causes the filter to add a "DMARC-Filter" header field indicating the
##  presence of this filter in the path of the message from injection to
##  delivery.  The product's name, version, and the job ID are included in
##  the header field's contents.
#
SoftwareHeader true

##  Syslog { true | false }
##      default "false"
##
##  Log via calls to syslog(3) any interesting activity.
#
Syslog true

##  SyslogFacility facility-name
##      default "mail"
##
##  Log via calls to syslog(3) using the named facility.  The facility names
##  are the same as the ones allowed in syslog.conf(5).
#
# SyslogFacility mail

##  TemporaryDirectory path
##      default /var/tmp
##
##  Specifies the directory in which temporary files should be written.
#
# TemporaryDirectory /var/tmp

##  TrustedAuthservIDs string
##      default HOSTNAME
##
##  Specifies one or more "authserv-id" values to trust as relaying true
##  upstream DKIM and SPF results.  The default is to use the name of
##  the MTA processing the message.  To specify a list, separate each entry
##  with a comma.  The key word "HOSTNAME" will be replaced by the name of
##  the host running the filter as reported by the gethostname(3) function.
#
# TrustedAuthservIDs d


##  UMask mask
##      default (none)
##
##  Requests a specific permissions mask to be used for file creation.  This
##  only really applies to creation of the socket when Socket specifies a
##  UNIX domain socket, and to the HistoryFile and PidFile (if any); temporary
##  files are normally created by the mkstemp(3) function that enforces a
##  specific file mode on creation regardless of the process umask.  See
##  umask(2) for more information.
#
UMask 0002

##  UserID user[:group]
##      default (none)
##
##  Attempts to become the specified userid before starting operations.
##  The process will be assigned all of the groups and primary group ID of
##  the named userid unless an alternate group is specified.
#
UserID opendmarc

CopyFailuresTo postmaster@kernel-error.de
ForensicReports true
ForensicReportsBcc postmaster@kernel-error.de
ForensicReportsSentBy postmaster@kernel-error.de
HistoryFile /var/run/opendmarc/opendmarc.dat
MilterDebug 0

Nach der Konfiguration sollte sich der Milter bereits starten lassen. Das mache ich nun mal und kontrolliere ob er läuft!

$ /etc/init.d/opendmarc start
$ netstat -ltnp | grep :8893
tcp        0      0 127.0.0.1:8893          0.0.0.0:*               LISTEN      15974/opendmarc

Es muss nur noch Postfix darüber informiert werden, dass der Milter genutzt werden soll. Ich erweitere also einfach die folgenden Optionen. Dabei sollte der DMARC-Milter natürlich als letztes stehen:

$ vi /etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:54321, inet:localhost:8893
non_smtpd_milters = inet:127.0.0.1:54321, inet:localhost:8893

Ich sag es ja, die grobe Konfiguration ist erstmal extrem einfach. Nun geht es nach dem Testen an einen Feinschliff und eine saubere Konfiguration. Tja…. Noch Fragen? Dann fragen 🙂

📧 E-Mail-Header: In-Reply-To & Message-ID einfach erklärt

LEUTE… am 13 August 1982 wurde von einem Herrn David H. Crocker das RFC 733 überarbeitet. Somit wurde das RFC 733 ersetzt durch das RFC 822.

In diesem nun knapp 32 Jahre alten Dokument wurden die Mailheader In-Reply-To und Message-ID definiert. Warum ich das schreibe? Ganz einfach… Weil es noch nicht bei allen angekommen zu sein scheint, was jetzt nicht böse zu verstehen ist!

Ich möchte es daher einmal kurz erklären. Sollte ich jemanden auf diesen Eintrag verweisen, also bitte lesen smile

Wenn ich eine E-Mail an Klaus schreibe, dann erhält meine E-Mail automatisch eine einmalige Message-ID. Diese landet dann, für den Anwender unsichtbar im Mailheader. Antwortet Klaus nun auf diese E-Mail, bekommt seine Antwort natürlich ebenfalls eine MessageID, zusätzlich wird noch das Feld In-Reply-To gefolgt von der MessageID der Nachricht auf welche er gerade geantwortet hat in die E-Mail Header geschrieben.

Was bringt dieses? Nun, viele E-Mail Clients (japp Outlook seit ein paar Jahren auch) können E-Mail Nachrichten in der Form eines Gesprächsverlaufes anzeigen. Selbst wenn sich Betreff oder E-Mail-Inhalt komplett ändern. Dieses macht einem nicht nur das nachträgliche Verfolgen der E-Mail Kommunikation einfacher, sondern erleichtert einem extrem die Übersicht zu behalten. Da die E-Mail ja an eine völlig falsche Stelle einsortiert wird.

Alles funktioniert perfekt bis zu dem Moment in welchem jemand in einem völlig anderem Zusammenhang auf eine E-Mail antwortet. Also irgendeine alte E-Mail heraussuchen, auf antworten klicken, Betreff und Hinhalt löschen und eine „neue“ E-Mail schreiben. Das verbrennt nicht nur die Übersicht, sondern sorgt dafür das E-Mails sehr spät oder überhaupt nicht gelesen/beantwortet werden.

Habe ich dich auf diesen Text verwiesen, dann möchte ich dich (aus dem genannten Grund) mit Nachdruck darum bitte, mit bei neuen Themen eine neue E-Mail zu schreiben. Alle anderen nehmen es bitte als Information auf!

Für Detail bitte im RFC 822 besonders den Punkt 4.6.2.  IN-REPLY-TO lesen: http://www.ietf.org/rfc/rfc0822.txt und natürlich RTFM beim eigenen MUA betreiben. Bei Fragen, einfach fragen wink

« Ältere Beiträge Neuere Beiträge »

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑