milter quota for Maildir

This is a backend cgi that works with Maildir, and complements the previous milter quota posting.

Be careful! This is only a proof-of-concept. It does not do any sort of caching, nor does it use UDP.

Apparently, the standard Maildir++ specification dictates that everyone must update the maildirsize file when doing any operation in Maildirs. So we don’t have to do heavy filesystem operations to get current mailbox size, we can read it from this file..

#!/usr/bin/perl
# This is quota.cgi for Maildir # http://wiki.dovecot.org/Quota/Maildir

use CGI qw(:standard);

$username = param("u");
exit if ($username eq "");

$home = "/var/mail";

$file=$home . "/" . $username . "/Maildir/maildirsize";
open(FILE, "< $file") or die "OK $file does not exist.";
@lines = <FILE>;
close(FILE);

($quota, $msgquota) = split(" ", $lines[0]);
$quota=int($quota); $msgquota=int($msgquota);
$line=0; $size=0; $msgs=0;
do {
 $line++;
 ($msgsize, $msgcount) = split(" ", $lines[$line]);
 $size+=$msgsize; $msgs+=$msgcount;
} while ($line< =$#lines);

if (($size>$quota) || (($msgs>$msgquota) && ($msgquota!=0))) {
    print "OVERQUOTA $username $size $quota $msgs $msgquota\n";
} else {
    print "OK $username $size $quota $msgs $msgquota\n";
}

(Ref)

Advertisement

ORDB bounces

Η ordb ήταν μια dnsbl με open relay servers που χρησιμοποιούσαν πολλοί mail servers. Εχει σταματήσει τη λειτουργία της όμως από το Δεκέμβρη του 2006..

Επειδή όμως πολλοί ξεχασμένοι εξακολουθούν να τη χρησιμοποιούν (ενώ πλεον δεν έχει up-to-date data και δεν προσφέρει το επιθυμητό αποτέλεσμα) από χθες 25 Μαρτίου 2008 άρχισε να επιστρέφει false positives σε όλα τα queries προς αυτή.

Για παράδειγμα, μέχρι να αλλάξουν το configuration στους mail servers του in.gr δε δέχονται κανένα mail…

$ telnet mail.in.gr 25
Trying 194.63.247.43...
Connected to mail.in.gr.
Escape character is '^]'.
220 IN_MAIL_SERVER.in.gr ESMTP
helo test.host.gr
250 eml3.in.gr Hello test.host.gr [192.168.1.2], pleased to meet you
mail from:nobody@forthnet.gr
553 5.3.0 Rejected - see http://ordb.org/
quit
221 2.0.0 eml3.in.gr closing connection

(via)

milter verify from

Μετά το milter-quota, ένα ακόμα milter βασισμένο στο sample.pl του Sendmail::Milter. Χρειάζεται και το Net::LDAP.

Υποθέτει ότι έχουμε έναν authoritative LDAP με όλα τα emails για τα domains που είναι υπεύθυνος ο mail server μας. Αν κάποιος πάει να μας στείλει mail με envelope from address (από δικό μας domain) που όμως δεν υπάρχει στον LDAP, το κάνουμε REJECT. Ετσι γλιτώνουμε το spam και backscatter από πολλά malware που στέλνουν κάνοντας randomize το from address και κολάνε το domain στο τέλος..


use Net::LDAP;

sub envfrom_callback
{
        my $ctx = shift;
        my @args = @_;

        $email=@args[0]; # format is <user @dom.ain>
        $email =~ s/< (.*)>/$1/; # strip <>
        ($username, $domain) = split (/@/, $email);
        #print "username=$username domain=$domain\n";

        $ldap = Net::LDAP->new("ldapserver");
        $ldap->bind("cn=postmaster,ou=sendmail,dc=mail", password=>"xxxx");
        $mesg = $ldap->search(filter=>"(sendmailMTAClassValue=$domain)",
                 base=>"sendmailMTAClassName=LDAPRoute,ou=classes,ou=sendmail,dc=mail");
        @entries = $mesg->entries;

        if (@entries) { # domain exists in our LDAP
                #print "domain $domain exists in our LDAP, so perform user lookup\n";
                $mesg2 = $ldap->search(filter=>"(mailLocalAddress=$username\@$domain)",
                        base=>"ou=$domain,ou=hosted,dc=mail");
                @entries2 = $mesg2->entries;

                if (@entries2) { # user exists in ldap
                        #print "address $username\@$domain exists in ldap. accept.\n";
                        return SMFIS_CONTINUE;
                } else {
                        #print "address $username\@$domain does not exist in ldap. reject.\n";
                        $ctx->setreply('550', '5.7.1', "Reject: your From address $email does not exist."); #rfc3463
                        return SMFIS_REJECT;
                }
        } else { # domain is not in our LDAP
                #print "domain $domain does not exist in LDAP. accept.\n";
                return SMFIS_CONTINUE;
        }
}

Αλλα παρόμοια milters:

milter quota

Ενα milter για να γλιτώσουμε (κι άλλο) backscatter.

Υποθέτουμε οτι στο mail σύστημά μας έχουμε Frontend και Backend mail servers.

Ενας τυπικός frontend mail server κάνει μία σειρά από ελέγχους, πχ. Reverse DNS Lookups, dnsbl lookups, whitelist/blacklist checks, Level-1 attachment cut-off, Anti-Virus scan κλπ.

Το mail που περνάει επιτυχώς όλα τα παραπάνω, πρέπει να πάει στους backend servers και αφού γραφτεί στο mailbox, να περιμένει τον χρήστη να το διαβάσει. Στην περίπτωση όμως που ο χρήστης υπερβαίνει το quota του, τότε το backend δε θα καταφέρει να γράψει το mail στο mailbox, και θα αναγκαστεί να στείλει ένα NDR bounce message, το οποίο είναι backscatter..

Χρειαζόμαστε ένα μικρό (web)service στο backend, που θα μας λέει αν ένα mailbox είναι στο όριο ή όχι (overquota).

Για παράδειγμα αυτό το cgi script:

#!/usr/bin/perl
# This is /cgi-bin/quota.cgi

use CGI qw(:standard);

$username = param("u");
exit if ($username eq "");

$quota=200*1024*1024; # assume 200MB quota
$home="/var/mail"; # assume mbox format

$size = ( -s "$home/$username" );

print "Content-Type: text/plain\n\n");

if ($size>quota) {
    print "OVERQUOTA $username $size $quota\n";
} else {
    print "OK $username $size $quota\n";
}

Στο frontend εγκαθιστούμε τα perl modules LWP και Sendmail::Milter.

Παίρνουμε το sample.pl από το Sendmail::Milter και το διαμορφώνουμε κατάλληλα:

use LWP::Simple;

sub envrcpt_callback
{
        my $ctx = shift;
        my @args = @_;

        $email=@args[0]; # format is <user @dom.ain>
        $email =~ s/< (.*)>/$1/; # strip <>
        ($username, $domain) = split (/@/, $email);

        $be_response = get("http://$backend/cgi-bin/quota.cgi?u=$username");

        if ($be_response =~ /OVERQUOTA/) {
                #print "$email overquota\n";
                #RCODE 452 Requested action not taken: insufficient system storage (RFC 2821)
                #XCODE 4.2.2 Mailbox full (RFC 3463)
                $ctx->setreply('452', '4.2.2', "Quota exceeded for $email, try again later");
                return SMFIS_TEMPFAIL;
        }
        else {
                #print "$email not overquota\n";
                return SMFIS_CONTINUE;
        }
}

Το mail προς κάποιο overquota mailbox γίνεται tempfail και όχι reject, ώστε αν ο χρήστης αδειάσει το mailbox του να πάρει τα mails αργότερα..

Update: There is now a proof-of-concept cgi script for Maildir.

inbox-outbox minutes

Μόλις κυκλοφόρισαν τα πρακτικά του anti-spam workshop που είχα παρακολουθήσει το Νοέμβρη στο Inbox-Outbox.

"The workshop was set up in order to bring technical and non-technical
anti-spam experts together to give an overview about current situation
in the area of anti-spam. Professionals from both sides gave
contributions about spam trends, current legal and technical anti-spam
issues and newest research results.

Discussions during the workshop made clear that providers are fighting
spam, but need support from different areas. In general, support from
legal experts is highly appreciated by providers. They often seem to
stumble in difficult legal aspects regarding email or virus filtering.
This workshop made clear which measures are actually desirable and
required by policy makers. Moreover, providers welcomed the efforts from
research institutes developing new anti-spam technologies.

All in all, the results of the workshop and ENISA's upcoming deliverable
on provider security measures give a comprehensive overview about
current anti-spam best practice. However, during the workshop it raised
up that spam should be considered as a symptom of network abuse. Solving
spam therefore requires, next to current efforts, also approaches to
mitigate net abuse in general. As a consequence, ENISA will concentrate
next year on resilience as a main part of its Working Programme 2008 and
put forth efforts making network abuse more transparent to legal and
technical experts."

Thanks Pascal ;)