Preventing SMTP Auth abuse

One of the biggest problems I have had to deal with over the past few years has been abuse of authenticated SMTP. Spammers occasionally manage to obtain a customer’s username and password and use these to send email via our servers with authenticated SMTP.

It’s not as easy to prevent this as it is to prevent other attempts to block spammers as we need to ensure that genuine customers are able to send email without problems. The solution is not however enormously difficult and a discussion I had today has encouraged me to publish the generic bits of it so others can use it or pick holes as appropriate.

WordPress does horrible things to the code indenting so you’ll need to forgive the horrible style.

use Tie::Hash::Expire;
use File::Tail;

if ( $> != 0 ) {
    die "You must be root to run this command";
my %seen = ();
tie %seen, 'Tie::Hash::Expire', { expire_seconds => 1200 };
my $line = undef;
my $log = File::Tail->new(name => "/var/log/mail.log", tail => -1);
while ($line = $log->read) {
    next unless $line =~ /: client=.*\[(.*)\], sasl_method=(.*), sasl_username=(.*)/;
    my $ip = $1;
    my $user = $3;
    $user =~ s/, sasl_sender=.*$//;


    my $size = keys %{$seen->{$user}};
    if ($size > 2 ) {
        # "Customer $user looks like they have been compromised\n";
        my ($l, $d) = split /@/, $user;
        if ( $d ) {
            # full email address - local part is $l and domain is $d
            # XXX Do something here to suspend the account - change password?
    else {
        # just a username. Again suspend it

This should be fairly clear. All it does is to tail the mail log file and track the sasl login and the IP address of the client connection. If the same user login connects to the authenticated SMTP service from more than 2 client IP addresses within a short time some action is taken to suspend the account.

On our real implementation of this there is a further check on the client IP address so that we don’t track connections if we recognise the IP address as belonging to a customer broadband connection.

This entry was posted in Code, Email, Perl, Postfix, SPAM. Bookmark the permalink.