> Has anyone got any kind of working parts they could share to
> block these zombie connections at the IP level?
Mark -- here are two things I've tried -- neither are great, but they
are starting points, perhaps others would like to take these and
modify / improve them? I'm hesitant to put these out there, because
they're very alpha / test-quality; really, more should be done to make
them more robust. But, they've worked for me, and I'd be delighted if
someone else wants to pick up from here and improve them.
I've been finding that the zombies come from all over the place, and
generally, any given zombie doesn't try more than a few attempts.
First attempt: find all connections that have been active for 5
minutes or longer, and kill them. This catches connections that are
tarpitted. It also catches connections that are taking a long time to
send data, potentially legit; in our case, I'm happy killing anything
that can't transmit 10 MB of data within 5 minutes.
Since most the zombies only seem to try a few times from any IP, this
seems to work quite well -- i.e. there's nothing here that prevents re-
connects, but zombies don't seem to attempt reconnects currently.
This is designed to be run from cron once a minute.
> #!/usr/bin/perl
>
> $MAX_AGE = 300;
>
> @jobs = `ps -eo ppid,lstart,cmd | grep 'submit esmtp dns' | grep -v
> grep`; # We need submit's parent process id, since that's what we
> need to kill -- hence ppid, not pid
>
> use Date::Parse;
>
> while ($job = pop @jobs) {
> if ($job =~ /([0-9]+)\s+(.*)\s+submit esmtp dns(.*)/) {
> $ppid = $1;
> $age = time() - str2time($2);
> $connectionInfo = $3;
> $connectionInfo =~ /([0-9\.]+)\]\)/;
> $ipAddr = $1;
> $connectionInfo =~ s/^\;\s+//;
> if ($age > $MAX_AGE && $age < 7200) { # 7200 isn't necessary,
> but
> sanity check in case something changes and this breaks -- wouldn't
> want to randomly kill wrong things
> print "Killing submit[$ipAddr] -- $ppid ($age seconds
> for
> $connectionInfo)\n";
> `kill $ppid`;
> }
> }
> }
Second attempt: Read maillog in real time and selectively block IPs
that are attempting to send to too many invalid users or are otherwise
blocked and retrying. This doesn't seem to work so well in practice,
because the zombies are coming from all over the place, so this just
generates a really large iptables list.
This is designed to run in the background. You should periodically
flush the iptables list (SMTPBLOCK in this example), so that it
doesn't grow unbounded.
> #!/usr/bin/perl
>
> close(STDOUT);
> open(STDOUT, ">>/var/log/smtp-graylist") || print STDERR "failed to
> open stdout: $!";
>
> close(STDERR);
> open(STDERR, ">>/var/log/smtp-graylist") || print "failed to open
> stderr";
>
> close(STDIN);
>
> # Exit parent process (so we run like a daemon):
> if (fork() != 0) {
> exit(0);
> }
>
>
> $sleepCount = 60;
> $loopCount = 0;
> while (1) {
> $loopCount++;
> if ($loopCount > 5000) { $loopCount = 0; %IP_SCORES = {}; }
>
> if ($sleepCount >= 60) {
> close FILE;
> open (FILE, "/var/log/maillog") || die "Can't read maillog: $!";
> seek(FILE,0,2);
> $sleepCount = 0;
> }
> seek(FILE,0,1);
> $ret = read(FILE, $thisRead, 8192);
> if ($ret != 0) {
> @lines = split(/\n/, $thisRead);
> foreach $line (@lines) { examineMaillogLine($line); }
> $sleepCount = 0;
> } else {
> sleep(1);
> $sleepCount++;
> }
> }
>
>
> sub examineMaillogLine {
> my ($line) = @_;
> unless ($line =~ /\:ffff\:([0-9\.]+)/) { return; } # Example line:
> ip=[::ffff:10.101.187.210]
> my $ip = $1;
> if ($line =~ / 511 /) { $IP_SCORES{$ip} += 5; }
> elsif ($line =~ /513 Relaying denied/) { $IP_SCORES{$ip}++; }
> elsif ($line =~ /550 User unknown/) { $IP_SCORES{$ip}++; }
> elsif ($line =~ /502 ESMTP command error/) { $IP_SCORES{$ip} += 4; }
> else { return; }
>
> if ($IP_SCORES{$ip} >= 10) {
> `/sbin/iptables -A SMTPBLOCK -s $ip -p tcp --dport 25 -j DROP`;
> }
> }
------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations
Conference from O'Reilly Media. Velocity features a full day of
expert-led, hands-on workshops and two days of sessions from industry
leaders in dedicated Performance & Operations tracks. Use code vel09scf
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
courier-users mailing list
[email protected]
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-users