Tag Archives: spam

Hey, watch this!

I had a teflon tape moment (to borrow a metaphor from MJD) recently in discovering the watch command.

You know how you run the same command repeatedly, trying to see if it changed? Like ls -la file.name to see when it’s done downloading, or ps ax | grep foo to see if a particular process has terminated, or whatever. Well, turns out that the watch command does exactly that:

watch -n 10 ls -la file.name

Now, you were already aware of that, and have been using it for years, or it’s a completely new thing to you, and you’ll wonder why you never knew about it. Like teflon tape.

I now use this command several times a day, and can’t imagine how I put up with all that extra typing before. Right now, I’m using it to watch my firewall ruleset change as the spam pours in. The spammers seem extra busy this week.

Blocking more spammers

This won’t work for everyone, but perhaps it will give you an easy place to start.

I’ve noticed lately that I’m getting HUNDREDS of messages to bogus email addresses in the space of a few minutes, or perhaps hours, from a particular address or block of addresses. I suppose the theory is that if they send to <dictionary>@rcbowen.com it will eventually hit a valid address.

The goal here is to identify a host that is sending these kinds of messages, and just block them at the firewall. I want to make sure that they are not one of my secondary MX’es, which, by no fault of their own, are just relaying messages to me. And I want to make sure that I don’t block someone who innocently mistypes an address. So there are some checks for that. Specifically, I have a list of addresses that are valid MXes. And I only inflict punishment if they send more than 5 messages.

The /usr/bin/BLOCK script is a shell script that adds them to my firewall deny list. Since that’s typically a one-liner, it’s left as an exercise to the sysadmin.

#!/usr/bin/perl
use strict;
use warnings;

my @exceptions = qw(mx.hostname.com mx2.otherhost.net trusted.host.org);
my %spammers = ();

while (<>) {
    next unless /User unknown in local/;
    my $skip = 0;
    s/.*?RCPT from (.*?):.*$/$1/;
    foreach my $x (@exceptions) {
        $skip++ if m/$x/;
    }
    next if $skip;

    # So, we should now have someone that's not an MX, who just sent
    # us email to a bogus address. What should we do about it?
    my $spammer = $_;
    $spammer =~ s/^([^[]*)[//;
    my $host = $1;
    $spammer =~ s/][^]]*$//;
    $spammers{$spammer}++;


    if ($spammers{$spammer} > 5) {
        # This person is almost certainly a spammer.
        warn "$host (at $spammer) appears to be a spammer. Adding them to the firewall";
        # Except, if they are passing bogus stuff in the address,
        # somehow. Not that I think they could ...
        if ($spammer =~ /[^.d]/) {
            warn "Hmm. Troubling. Strange stuff in the address. Better skip this one";
            next;
        }
        `/usr/bin/BLOCK_no_log $spammer`;
        # And now we don't need to keep that data around any more
        delete $spammers{$spammer};
    }
}

To use this, just pipe syslog through it, thus:

tail -f /var/log/maillog | ./nukespammers.pl