Mein Jabber Server hat gerade neue Zertifikate bekommen. Die alten waren ausgelaufen…. Ich spare mit die Fingerprints, prüft bitte per TLSA 😀
So long…
Datenhaufen zu IT und Elektronik.
Mein Jabber Server hat gerade neue Zertifikate bekommen. Die alten waren ausgelaufen…. Ich spare mit die Fingerprints, prüft bitte per TLSA 😀
So long…
Zur Prüfung von TLSA RECORDS gibt es inzwischen viele lustige Tools und Webseiten im Internet. Wenn man es aber einmal selbst gemacht hat, dann wird einem klar was überhaupt passiert.
In meinem Beispiel geht es um die Prüfung des TLSA-RECORDS meines Mailservers. Dazu baue ich erst per openssl eine Verbindung zu Postfix auf und starte dann mittelst STARTTLS die gesicherte Verbindung. Dabei wird das Serverzertifikat übermittelt (Bild).
$ openssl s_client -starttls smtp -connect smtp.kernel-error.de:25
Hier kopiert man sich nun den Zertifikatsteil heraus und speichert diesen einfach in einer Textdatei zwischen (Bild). Als nächstes erstelle ich die SHA256 Checksumme über das öffentliche Zertifikat meines Postfix.
$ openssl x509 -in test.crt -outform DER | openssl sha256 (stdin)= 94c8e1bdfff4f6d3fec0c4e2f26293d78870650bfd3534e77b93cdaccb77eb95
Als Vergleich muss nun der TLSA-RECORD herhalten. Diesen hole ich mir mit dig aus der DNS-Zone. Die 1 beutet dabei das die komplette Zertifikatskette gültig sein muss, damit dieses Zertifikat als gültig angesehen wird. Die 0 bedeutet das die Checksumme über das komplette Zertifikat erstellt wurde und die 1 bedeutet das es eine SHA256 Checksumme sein muss.
$ dig _25._tcp.smtp.kernel-error.de IN TLSA +short 1 0 1 94C8E1BDFFF4F6D3FEC0C4E2F26293D78870650BFD3534E77B93CDAC CB77EB95
Nun vergleiche ich die beiden Checksummen:
94c8e1bdfff4f6d3fec0c4e2f26293d78870650bfd3534e77b93cdaccb77eb95 94C8E1BDFFF4F6D3FEC0C4E2F26293D78870650BFD3534E77B93CDACCB77EB95
Sind sie identisch, ist alles perfekt. Möchte man nun einen TLSA RECORD eines anderen Anbieters prüfen greift man sich am besten zuerst dessen TLSA RECORD aus dem DNS. Dann sieht man welche Checksumme in welcher Art erstellt werden muss. Ebenfalls wird klar ob man die komplette Zertifikatskette prüfen muss oder nicht.
Viel Spaß!
Ich hatte es ja bereits erwähnt… Wer „einfach“ testen möchte ob sein Mailserver bzw. seine RECORDS für diesen korrekt sind, nutzt am besten posttls-finger:
# posttls-finger -t30 -T180 -c -L verbose,summary kernel-error.de posttls-finger: initializing the client-side TLS engine posttls-finger: using DANE RR: _25._tcp.smtp.kernel-error.de IN TLSA 1 0 1 94:C8:E1:BD:FF:F4:F6:D3:FE:C0:C4:E2:F2:62:93:D7:88:70:65:0B:FD:35:34:E7:7B:93:CD:AC:CB:77:EB:95 posttls-finger: setting up TLS connection to smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25 posttls-finger: smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: TLS cipher list "aNULL:-aNULL:ALL:!EXPORT:!LOW:+RC4:@STRENGTH:!aNULL" posttls-finger: smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: depth=1 verify=0 subject=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 2 Primary Intermediate Server CA posttls-finger: smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: depth=1 verify=0 subject=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 2 Primary Intermediate Server CA posttls-finger: smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: depth=0 verify=1 subject=/description=y0xkuso3gx7t8h0o/C=DE/ST=Nordrhein-Westfalen/L=Sprockh\xF6vel/O=Sebastian Van De Meer/CN=smtp.kernel-error.de/emailAddress=postmaster@kernel-error.de posttls-finger: smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: depth=0 matched end entity certificate sha256 digest 94:C8:E1:BD:FF:F4:F6:D3:FE:C0:C4:E2:F2:62:93:D7:88:70:65:0B:FD:35:34:E7:7B:93:CD:AC:CB:77:EB:95 posttls-finger: smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: subject_CN=smtp.kernel-error.de, issuer_CN=StartCom Class 2 Primary Intermediate Server CA, fingerprint=E1:92:93:D4:CA:E9:5D:44:B5:CC:A4:15:1F:12:A6:E0:B5:C2:97:56, pkey_fingerprint=E9:84:8E:51:47:99:90:53:0B:2C:2E:1E:70:6E:DE:CA:A4:65:8A:C5 posttls-finger: Verified TLS connection established to smtp.kernel-error.de[2a02:c200:0:10:3:0:4297:1]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Na schau mal einer an… Das Browser Plugin für den DNSSEC Validator kann nun auch DANE / TLSA und er zeigt es angenehm übersichtlich an.
https://www.dnssec-validator.cz/pages/download.html
Ist in jedem Fall noch mal einen Klick wert 🙂
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
Typ | Priorität | Hostname | Verweist auf die Adresse | Gültigkeitsdauer |
MX | 0 | @ | kernel-error-com0i.mail.protection.outlook.com | 1 Stunde |
CNAME | – | autodiscover | autodiscover.outlook.com | 1 Stunde |
Typ | TXT-Name | TXT-Wert | Gü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
Typ | Dienst | Protokoll | Port | Stärke | Priorität | Gültigkeitsdauer | Name | Ziel |
SRV | _sip | _tls | 443 | 1 | 100 | 1 Stunde | kernel-error.com | sipdir.online.lync.com |
SRV | _sipfederationtls | _tcp | 5061 | 1 | 100 | 1 Stunde | kernel-error.com | sipfed.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
Typ | Hostname | Verweist auf die Adresse | Gültigkeitsdauer |
CNAME | msoid.kernel-error.com | clientconfig.microsoftonline-p.net | 1 Stunde |
Ich LIEBE es ja, immer wenn Microsoft solche Dinge ins Deutsche übersetzten 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….
Ich habe gerade ein kleines IPv6 Quiz gefunden. Es stellt 10 einfache Fragen und man hat 10 Minuten Zeit. Wer also Lust auf ein kleines Quiz hat: http://www.proprofs.com/quiz-school/story.php?title=NTkwODc3
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!
Bin ich heute wieder zu böse?
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!
Oh, da ging ja heute ein kleines Beben durchs Internet. Eine weitere RIR ist schon am letzten /8, die ARIN…. Ich bin ja fast vom Glauben abgefallen, das hat tatsächlich noch einige Leute überrascht O_o
Hallo!?!?! 2014 und so?!?!?
https://www.arin.net/resources/request/ipv4_countdown.html
Wann werden die Herren wohl mal wach?!? Jetzt hat also nur noch die AFRINIC etwas Luft.
Das gefällt mir … 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
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 . 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.
© 2025 -=Kernel-Error=-
Theme von Anders Norén — Hoch ↑