E-posta sunucuları için bir IP bloklama uygulaması

Problem:

Bir süre önce sunucularımızdan biri üzerinden ara ara ciddi miktarda e-posta gönderildiğini gözlemlemiştim. Sunucu, güncel spam önleme yazılımları ve ince ayarlar ile korunmasına karşın bu durumun nasıl meydana geldiğini anlamak biraz zaman aldı.

Sonuçta ortaya çıkan durum şu; müşterilerimizden birinin kullandığı e-posta hesabının şifresi bir virüs veya trojan yoluyla ele geçirilmiş. Korsanlar bu hesabı kullanıp, geçerli bir SMTP doğrulaması ile Ukrayna, Rusya ve Fransa’dan beş farklı IP adresi üzerinden spam mesajlarını göndermeyi başarmışlar…

Amaç:

Yurtdışından SMTP doğrulaması yoluyla e-posta gönderilerini durdurmak hatta ilgili IP’lerin sunucu erişimlerini tamamıyla engellemek. Bunu yaparken tipik bir sunucuda kurulu bulunması gereken standart uygulamalardan yararlanmak.

Çözüm:

Basit bir betik yardımıyla maillog dosyalarının düzenli aralıklarla taranması ve yurtdışı kaynaklı SMTP doğrulaması yapmaya çalışan IP adreslerinin sunucu erişimlerinin bloklanması. Bu çözüm çok farklı şekillerde geliştirilmeye açık; örneğin yurtiçi veya yurtdışı olsun belirli bir süreden -mesela 30 saniye- kısa aralıklarla gerçekleştirilen SMTP bağlantılarının  bloklanması, belirli ülkelerden SMTP doğrulaması yapan IP’lerin bloklanması vs.

Hazırladığım betiği aşağıya kopyaladım. Eğer benzer bir sorun yaşıyorsanız ve sunucunuza doğrudan “root” erişiminiz varsa bu betik işinize yarayabilir. Serbestçe kullanabilirsiniz…

#!/usr/bin/perl

# onlytr.pl v1.0
#
# This script will help to stop and block SMTP Authentication
# attempts outside from Turkey (TR), using iptables and maillogs.
# Can easily be adjusted to include and/or exclude other
# countries as well.
#
# Please notice that the Geo::IP Perl Module and a recent
# GeoIP.dat country database file is necessary.
#
# Author (c) 2013 Mahir B. Asut - mahir.asut.net
#
# This software ise Public Domain. Please feel free to use
# and distribute.
#
# This software utilizes GeoLite data created by MaxMind,
# available from www.maxmind.com
#
# Usage: First check and edit the Config Section below if necessary.
# Run directly from the server console as root user or create a cron job.
# Tested on RHEL derivatives.

use strict;
use Geo::IP;

my $gi = Geo::IP->new(GEOIP_MEMORY_CACHE);

# START - Config Section 

my $maillog = '/var/log/maillog';
my $iptablessave = '/sbin/service iptables save';
my $iptablesrestart = '/sbin/service iptables restart';
my $iptablesdata = '/etc/sysconfig/iptables';
my $logfile = '/var/log/onlytr.log';

# END - Config Section

open INF,'<'.$iptablesdata || die;
my @data = <INF>;
my $iptablessource = join(';',@data);
close INF;

open INF,'<'.$maillog || die;
my @lines = <INF>;
close INF;

my $found;

foreach my $line (@lines) {
	if ($line =~ 'sasl_username') {
		chomp $line;
		my $ip = $line;
		$ip =~ s/^.*[(d+).(d+).(d+).(d+)].*$/$1.$2.$3.$4/;
		my $notice;
		if ($iptablessource =~ $ip) { $notice = 'already in iptables' }
		else {
			my $country = $gi->country_code_by_addr($ip);
			if ($country eq 'TR') { $notice = 'ip source TR' }
			else {
				$found = 1;
				$notice = 'ip source NOT TR! but '.$country;
				system ("iptables -A INPUT -s ".$ip." -j DROP");
				$iptablessource.= ';'.$ip;
				
				open OUTF,'>>'.$logfile || die;
				print OUTF $line."n";
				close OUTF;
			}
		}
		print $ip.': '.$notice."...n";
	}
}

if ($found) {
	system ($iptablessave);
	system ($iptablesrestart);
}

exit;