IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Autor: Sebastian van de Meer (Seite 27 von 46)

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.

Slow clap reaction GIF about Gmail privacy

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

Toll, oder? Super… Alle freuen sich…. 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!

Fragen? Einfach melden.

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: https://web.archive.org/web/20151222062444/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

Fragen? Einfach melden.

Mailgraph um SPF-, DMARC- und DKIM-Graphen erweitern

Mailgraph von David Schweikert ist ein simples Perl-Script, das Postfix-Logdateien parst und daraus RRDtool-Graphen erzeugt. Empfangene, gesendete, abgelehnte Mails auf einen Blick. Für kleinere Mailserver oder Testsysteme reicht das völlig.

Was mailgraph nicht kann: SPF-, DMARC– und DKIM-Ergebnisse darstellen. Wie viele Mails bestehen den SPF-Check? Wie oft schlägt DMARC fehl? Gibt es einen Trend? Ich habe zwar einen existierenden SPF-Patch für mailgraph gefunden, wollte aber alle drei Protokolle in einem Aufwasch.

Die folgenden Patches erweitern mailgraph 1.14 um drei zusätzliche Graphen: SPF (pass/none/fail), DMARC (pass/none/fail) und DKIM (pass/none/fail). Ausgelegt für Postfix mit postfix-policyd-spf, opendkim und opendmarc.

Installation

Auf einem Debian-System müssen zwei Dateien ersetzt werden: /usr/sbin/mailgraph (der Daemon) und /usr/lib/cgi-bin/mailgraph.cgi (die Weboberfläche). Vorher sichern.

Die Patches als Download: mailgraph-dmarc-spf-dkim.patch.tar.gz

Patch 1: /usr/sbin/mailgraph

Der Daemon-Patch fügt neun RRD-Datasources hinzu (spfnone, spffail, spfpass, dmarcnone, dmarcfail, dmarcpass, dkimnone, dkimfail, dkimpass) und parst die Logzeilen von policy-spf, opendmarc und opendkim:

*** 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;

Patch 2: /usr/lib/cgi-bin/mailgraph.cgi

Der CGI-Patch erzeugt die drei neuen Graphen (SPF, DMARC, DKIM) und bindet sie in die HTML-Ausgabe ein. Jeder Graph zeigt pass als Fläche, none als Stack und fail als Linie:

*** 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';
  my $rrd_virus = '/var/lib/mailgraph/mailgraph_virus.rrd';
***************
*** 32,37 ****
--- 36,50 ----
  	sent       => '000099',
  	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:rmsrspfnone: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',
+ 	);
+ }
+
  [...]

+ 		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";

  [...]

+ 		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);
+ 		}

Was die Patches tun

Der Daemon-Patch erweitert die RRD-Datenbank um neun Datasources und erkennt im Syslog die Ausgaben von drei Diensten:

DienstLog-PatternErgebnis
policy-spfReceived-SPF: pass/none/*spfpass, spfnone, spffail
opendmarcpass/none/faildmarcpass, dmarcnone, dmarcfail
opendkimDKIM verification successful / no signature data / bad signature datadkimpass, dkimnone, dkimfail

Der CGI-Patch erzeugt drei neue Graphen unterhalb der bestehenden. Jeder zeigt pass als Fläche, none als Stack darüber und fail als rote Linie. Die Zeiträume (Tag, Woche, Monat, Jahr) werden wie bei den Standard-Graphen automatisch erzeugt.

Hinweise

Die Patches sind für mailgraph 1.14 geschrieben. Weil mailgraph die RRD-Datasources beim ersten Start festlegt, muss nach dem Patchen die bestehende mailgraph.rrd gelöscht werden. Die alten Daten gehen dabei verloren, die neuen Graphen fangen bei Null an.

Es gibt auch einen separaten Patch für DANE-Graphen in mailgraph.

Wer heute mit dem Monitoring anfängt: rspamd bringt eine eigene Weboberfläche mit und prüft SPF, DKIM und DMARC in einem Durchgang. Zusammen mit Prometheus und Grafana bekommt man deutlich flexiblere Dashboards als mit RRDtool. Mailgraph bleibt trotzdem nützlich wenn man schnell was Schlankes braucht, das ohne externe Abhängigkeiten läuft.

Fragen oder Verbesserungsvorschläge? Einfach melden.

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

Fragen? Einfach melden.

DMARC-Prüfung in Postfix: OpenDMARC und rspamd im Vergleich

Eine DMARC-Policy zu veröffentlichen ist die eine Seite. Die andere ist, eingehende Mails gegen die DMARC-Policy des Absenders zu prüfen. Postfix kann das nicht selbst. Dafür gibt es zwei Wege: OpenDMARC als eigenständigen Milter oder rspamd, der DMARC als eines von vielen Modulen mitbringt.

Variante 1: OpenDMARC

OpenDMARC ist ein dedizierter DMARC-Milter. Er liest die Ergebnisse von SPF und DKIM aus den Mailheadern und prüft ob die DMARC-Policy des Absenders erfüllt ist.

# Debian/Ubuntu
apt install opendmarc

# FreeBSD
pkg install opendmarc

Die Konfiguration in /etc/opendmarc.conf:

AuthservID mail.example.de
Socket inet:8893@localhost
UserID opendmarc
SoftwareHeader true
Syslog true
RejectFailures false
HistoryFile /var/run/opendmarc/opendmarc.dat

RejectFailures false ist ein guter Startwert. Damit werden Mails die den DMARC-Check nicht bestehen nicht sofort abgelehnt, sondern nur markiert. So kann man erst beobachten bevor man scharf schaltet. AuthservID muss zum Hostnamen des Mailservers passen.

Wichtig: OpenDMARC verlässt sich darauf, dass SPF und DKIM bereits geprüft wurden und die Ergebnisse in den Authentication-Results-Headern stehen. Die Reihenfolge der Milter in Postfix ist daher entscheidend: SPF und DKIM müssen vor OpenDMARC laufen.

Postfix-Integration

In der main.cf den Milter registrieren. OpenDMARC muss nach dem DKIM-Milter stehen:

# main.cf
smtpd_milters = inet:localhost:8891, inet:localhost:8893
non_smtpd_milters = inet:localhost:8891, inet:localhost:8893

Port 8891 ist hier OpenDKIM, Port 8893 OpenDMARC. Nach einem postfix reload prüft OpenDMARC jede eingehende Mail und schreibt einen Authentication-Results-Header mit dem DMARC-Ergebnis.

Variante 2: rspamd

Wer rspamd als Spamfilter einsetzt, braucht keinen separaten DMARC-Milter. rspamd prüft SPF, DKIM und DMARC in einem Durchgang und verrechnet das Ergebnis mit dem Gesamtscore. Das DMARC-Modul ist standardmäßig aktiv und unterstützt auch DMARC-Reporting (rua/ruf).

Der Vorteil von rspamd: Statt einer harten Ablehnung bei DMARC-Fail fließt das Ergebnis in die Gesamtbewertung ein. Eine Mail die DMARC nicht besteht aber sonst sauber aussieht, wird nicht sofort abgelehnt. Umgekehrt kann eine Mail die DMARC besteht trotzdem als Spam markiert werden wenn andere Indikatoren dagegen sprechen.

Was passt besser?

OpenDMARCrspamd
AufwandEigener Dienst, eigene ConfigBereits als Milter integriert
VerhaltenHarte Entscheidung (reject/accept)Score-basiert, flexibel
ReportingEigenes Reporting-Tool nötigrua-Reports eingebaut
AbhängigkeitenBraucht SPF/DKIM in den HeadernPrüft SPF/DKIM selbst

Für neue Setups ist rspamd meist die bessere Wahl, weil es SPF, DKIM, DMARC, ARC und Spam-Filterung in einem Paket liefert. OpenDMARC ist sinnvoll wenn man einen minimalen Stack ohne Content-Filter will oder bereits einen anderen Spamfilter einsetzt.

Übrigens: DMARC und Mailinglisten vertragen sich nicht ohne Weiteres. ARC löst das Problem. Fragen? Einfach melden.

📧 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: https://datatracker.ietf.org/doc/html/rfc822 und natürlich RTFM beim eigenen MUA betreiben. Bei Fragen, einfach fragen wink

Siehe auch: DKIM-Schlüssel und E-Mail-Authentifizierung

Fragen? Einfach melden.

Kennwortgenerator

Bei mir ist mal wieder die Frage angekommen, wie man denn seine Kennwörter wählen sollte. Ich habe wieder auf das Programm pwgen hingewiesen. Das ist ein kleiner Password-Generator für die Bash/Konsole.

Warum ein Kennwort Generator? Nun ja, Software dieser Art hat aus meiner Sicht ein paar Vorteile…

So hindert man seinen eigenen Schweinehund daran immer das gleiche Kennwort zu benutzen. Das ist ja bekanntlich mehr als gefährlich, denn wenn bei irgendeinem Anbieter mal wieder ein Sicherheitsloch ausgenutzt wurde, ja dann ist das Kennwort schon in den „falschen Händen“, meist zusammen mit der E-Mail Adresse. Fast überall kann man sich mit der Kombination E-Mail Adresse/Kennwort anmelden. Ist es immer gleich, kann sich der Mensch mit den „falschen Händen“ direkt überall anmelden. Daher sollte es ein eigenes Kennwort für jeden Dienst geben. Dabei ist ein: SuperTollesKennwort.Dienstname besser als nichts… Nur so schlau dieses zu probieren ist im Zweifel der Mensch mit den „falschen Händen“ ebenfalls. Will man es auf die Spitze treiben legt man sogar für jeden Dienst eine eigene E-Mail Adresse an. Dann hat der Angreifer nicht nur kein einheitliches Kennwort, sondern auch keine einheitliche E-Mail Adresse. Zurück zu pwgen…

Als weiteren Vorteil sehe ich dass die erstellten Kennwörter „zufällig“ sind (es macht natürlich einen guten Kennwort Generator aus, dass er immer zufällige Kennwörter rechnet laughing). Einem selbst gehen schnell die Zufälle aus. Selbst wenn man immer nur auf der Tastatur hämmert, werden sie sich ähneln.

Zudem lässt sich pwgen gut in Scripten verwursten um direkt beim anlegen von Accounts schöne initiale Kennwörter zu generieren. Es wäre ja schön blöde immer die gleichen Kennwörter für neue Kunden zu vergeben. tongue-out

Nun wollen wir mal ein paar Kennwörter würfeln. Der folgende Aufruf sollte viele Kennwörter mit Groß-/Kleinschreibung, 8 Zeichen und Ziffern erstellen:

$ pwgen 
Puo7aone AG2aicho me0Ohn7t aiSeth7K aeb2Nah0 oGh1ohra iengahD0 ra4Aeboh
oNga5ooj doh0saeM eeMaiCo1 aeDoo8we IeXae1ah OoVael8h Soh7aera Ohnge6yi
aiH0quae ieSo7ohY noo4xe8E sheh5eeF uiChoh7e Aing2fae ieJii4to aeGu7tof
quooB9Be Ou1Onie4 Eeb9giep Chei8oob Yieh2yuz Naugh0be phai4aXe ohc7Ahw9
aiM0aiwo EiGhi9fu eiC2Xohk raiB0eu9 MuwuK5le Aicheew8 UDeo2eig xaig3Oph
kii0ER9E uKaig7uv ooha3Die Ahhoo5ba aTh7dook aeGh9mai Iewae8ig Shahye6s
Jieshie2 MooSa7th Tahj0dei tohb7Oto Ocahm7bi Ake5nah6 Boh7aung ThooV4ir
noo6Equ5 AhGhuz8i dotie8uN tae7Chai Mual8oaD ooP9IeQu aeg5Iido HahKie6u
Me8ahsei Ahg5ohpe Soh9ucol Eix1OoFa Ahleex9m ahch4Ahk Taev8Shi neu9Vei4
aiLoo5qu eiW2eiNg Zae8ooyu Eeng7koo ieZees1a tho1Chei bohh3ENe ooVeezu1
weeb4Ain daeMi8iR yohNg5iW Oogu1ac4 UFae3Fie kaiT5aak Wa6tie1u pheiw3Ye
Iyae4aef Shoh1aij pheong0K Toer8quu kohGu9Ta ceiChei0 iePh6she Taigh6mu
ooH0xair aGemai4i Zohdiah5 aesai2Oo uchohk7G ohxah9Oo AhJair1v thee6Io0
cah1kieG ieCh6cah Fi0aegeo ShiePee9 ooPafei2 oB4ohcho yoiPhu8I AiJ7beaM
Reexai7u AiCahj0s aePhai7E xaer6Uos ath4gi0U ieNgoo0i Ohfeech6 weet4Voo
iu8Dafis doo6Agee te7Hah7U oox3Eeri Eezas2th Eeyeer5g afiTah9K oot9aiCh
eiFaiNg9 Ooquahn9 jaiJah4z eo7oChai suph2Cau Tiebah1U uH0ohth0 uiS6iew0
Ej9iMee3 Phie4Ohh Iet7Aes1 pheiGh9r Jae3joh0 EiPh1iey Xo4Seejo ieque6Ci
booV4iex ieCae1Ee BaiMie8a waed6Fi1 Og5Ahth3 eiX4voph oopooQu1 phu0Xa3u
keishi0S Otievi4o ceeGh8Ee uthooZ6o Faed2sob udahG0Da Soh5aid1 reuze3Ne

So viele Kennwörter benötigt man normalerweise nicht. Ein einziges Kennwort mit Groß-/Kleinschreibung, 8 Zeichen und ohne Ziffern (dann kann es sich ein Anwender meist besser merken) generiert sich mit folgendem Aufruf:

$ pwgen -1 -0
chaisaeM

Soll es einmal sicher werden erstellt der folgende Aufruf ein Kennwort mit Groß-/Kleinschreibung, 14 Zeichen, Ziffern, Symbolen und der deaktivierten pronounceable Funktion von pwgen. Die pronounceable (aussprechbar) Funktion von pwgen sorgt sonst dafür das die Kennwörter besser zu merken sind. Dieses macht es natürlich etwas weniger zufällig.

$ pwgen -1 -s -y 14
SKf|.k.]m}o'Q3

Man sieht schon, solche Ausgaben lassen sich sehr gut in irgendwelchen Scripten nutzen! Wie immer bringen die man-pages noch mehr Beispiele und Informationen mit. Also bitte RTFM….

 $ man pwgen

 Ńoch Fragen? Dann fragen sealed

Fragen? Einfach melden.

Einmal mit Profis: Einblick in die Welt der Experten

Ich habe heute, wenn auch etwas angeschlagen, wieder vor einem System gestanden welches von einem „selbsternannten“ Profi eingerichtet wurde. Dabei gab es Fehler die ich jetzt nicht näher ausführen kann, denn noch ist es mal wieder Zeit für einen ordentlichen double facepalm!

Double facepalm reaction to professional mishaps

Nur falls sich jemand wundert warum ich in den nächsten Tagen dauerkopfschüttelnd herumlaufe. Jetzt glaubt bitte nicht dass ich fehlerfrei bin. Ganz sicher nicht!

Fragen? Einfach melden.

Yahoo macht Mailinglisten mit DMARC kaputt?

Na was lese ich denn da wieder bei golem.de? Yahoo soll Mailinglisten kaputt machen weil DMARC eingesetzt wird?

Über DMARC habe ich ja schon etwas geschrieben, auch dass man mit Mailinglisten Probleme bekommen kann, wenn man eine Policy veröffentlicht. Denn die meisten Mailinglisten arbeiten leider nicht DKIM konform. Denn DKIM signiert den Body und ebenfalls den Betreff einer E-Mail. Wenn die Mailingliste nun den Betreff ändert um ein [Mailinglistenname] in den Betreff zu schreiben (damit die Anwender darüber besser „filtern“ können und wegen Übersicht bla bla). Sowie einen kleinen Footer mit Infos zur Liste in den Body hängen, ja dann ist die DKIM Signatur ungültig. Soll ja so sein! Mailinglisten lassen sich prima über den Mail-Header: List-id Filtern, die Infos zur Mailingliste im Footer liest eh keiner und es produziert nur unnötig viele Daten, da sie an jede E-Mail gehangen werden. Übersicht? Filtert man seine E-Mail sauber und sortiert sie in die passenden Ordner, dann ist die Übersicht gegeben.

Wie auch immer… DKIM Signaturen werden durch Mailinglisten schon seit vielen Jahren gebrochen. Einige Mailinglisten werfen sogar die DKIM Signaturen aus den E-Mails bevor sie „weitergeleitet“ werden. Damit kann es zwar keine ungültige/gebrochene Signatur mehr geben, in Kombination mit einer DMARC Policy gibt es denn noch ein Problem. Denn wenn in der Policy steht: E-Mails sind immer DKIM und SPF signiert und wenn sie es nicht sind oder wenn die Signatur ungültig ist, dann weise die E-Mail zurück. Dann passiert das so!

All dieses ist schon seit längerem fest in ein RFC gegossen. Eingesetzt wird DMARC bereits von vielen der großen Anbieter… Bisher war nur noch keiner cool genug es „scharf“ zu schalten. Ist völlig legitim, denn auch die Mailinglisten Admins sollen eine gewisse „Übergangszeit“ haben. Wie so oft hat nur kaum einer reagiert. Ist ja nur mal wieder Security oder Features welche die User nicht direkt betreffen. Ja, es ist eine gewisse Art ~Vergewaltigung~!

Der DMARC-RECORD von yahoo.com gibt eine klare Policy vor:

$ dig IN TXT _dmarc.yahoo.com +short
"v=DMARC1\; p=reject\; sp=none\; pct=100\; rua=mailto:dmarc-yahoo-rua@yahoo-inc.com, mailto:dmarc_y_rua@yahoo.com\;"

Als Beispiel: Der DMARC-RECORD von gmail.com dagegen noch nicht:

$ dig IN TXT _dmarc.gmail.com +short
"v=DMARC1\; p=none\; rua=mailto:mailauth-reports@google.com"

Siehe auch: DMARC einrichten

Fragen? Einfach melden.

« Ältere Beiträge Neuere Beiträge »

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑