Original
Перевод: Сгибнев Михаил
Spamd - это sendmail-подобный демон, задачей которого является отсеивание спама.
Если пакетный фильтр PF сконфигурирован таким образом, что бы переадресовать порт 25 (SMTP)
на этот демон, то он постарается потратить впустую время и ресурсы отправителя спама.
Spamd спроектирован специально для того, что бы не загружать почтовый сервер, для чего
обнаруженный спам отклоняется с сообщениями об ошибке 450 или 550. До сего момента
борьба со спамом заключалась в том, что мы принимали и отбрасывали такую почту или
напрямую блокировали отправителя, spamd же, сконфигурированный на сообщение об ошибке 450,
отправит спам обратно отправителю.
Spamd лучше всего запускать из rc.
В моей сети нет почтового сервера, поэтому я использую spamd на каждой машине, которая напрямую получает почту.
Другими словами, если вы соединяетесь с 25-м портом машины из моей сети, то попадаете в цепкие руки spamd. Не
рекомендую этого делать!
Настройка осуществляется следующим образом:
- Отредактируйте /etc/spamd.conf таким образом, чтобы получилось нечто, похожее на нижеприведенное:
# $OpenBSD: spamd.conf,v 1.9 2004/01/21 08:07:39 deraadt Exp $
all:\
::
Это позволит обрабатывать все соединения.
-
В /etc/rc.conf добавляем строку:
spamd_flags="-b127.0.0.1 -v -s5 -nWelcome_To_The_Pit"
-
Для перенаправления трафика spamd, добавьте следущие строки в /etc/pf.conf:
rdr on $ext_if proto tcp from any to port smtp -> 127.0.0.1 port spamd
pass in quick on $ext_if inet proto tcp from any to lo0 port spamd synproxy state flags S/SA
- Запускаем spamd:
/usr/libexec/spamd -b127.0.0.1 -v -s5 -nWelcome_To_The_Pit
- По умолчанию, логи складываются в /var/log/deamon. Ниже представлен сценарий на Perl, складывающий всю
статистику в html файл. В задания cron прописана строка 50 23 * * * /var/www/cgi-bin/PantzSpamdStats.pl >>/dev/null 2>&1,
позволяющая запускать этот сценарий периодически.
#!/usr/bin/perl
################################
# Start Configuration Settings #
################################
# Set to "all" of you want all files (compressed also) read.
# Set to "one" if you just want the one file named "spamd" read.
$oneorallfiles = "all";
# Path to spamd logfile(s). No "/" after last dir name. Ex. "/var/log".
$spamdpath = "/var/log";
# Spamd log file (daemon by default)
$spamdfile = "daemon";
# Path to output html file
$spamdhtmlfile = "/var/www/htdocs/spamdstats.html";
##############################
# End Configuration Settings #
##############################
#####Begin: Assembling date code.#####
($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDaylightSavings) = localtime(time);
$Month += 1;
$Year += 1900;
if ($Month < 10) { $Month = "0" . $Month; }
if ($Hour < 10) { $Hour = "0" . $Hour; }
if ($Minute < 10) { $Minute = "0" . $Minute; }
if ($Second < 10) { $Second = "0" . $Second; }
if ($Day < 10) { $Day = "0" . $Day; }
#####End: Assembling date code.#####
#####Begin: Get one or all spamd filenames.#####
if ($oneorallfiles eq "all") {
@spamdfilenames = <$spamdpath/$spamdfile*>;
@spamdfilenames = sort { $b cmp $a } @spamdfilenames;
} else {
push(@spamdfilenames, "$spamdpath/$spamdfile");
}
#####End: Get one or all spamd filenames.#####
#####Begin: Read spamd file(s) and input data into a hash of arrays for sorting.#####
foreach $spamdlogfile (@spamdfilenames) {
open(IN, "gzcat -f $spamdlogfile |") or die ("Can't open file. Permissions?. UserID?");
while( <IN> ) {
if ((/spamd/) && (/disconnected after/)) {
($date,$hostname,$daemonandid,$ipaddress,$seconds) =
($_ =~ /(\w+\s{1,2}\d+ \d+:.\d:.\d+) (.*) (.*)\: (\d+\.\d+\.\d+\.\d+)\: disconnected after (\d+)/);
# Ipaddress is hash key. Update the 1st value in the array with seconds count calling old seconds count and
# adding it to the new count. Update the 2nd value in the array by 1. Count is per unique ip address hit.
$spamd_hash{$ipaddress} = [$spamd_hash{$ipaddress}[0] + $seconds,$spamd_hash{$ipaddress}[1] + 1];
}
}
close(IN);
}
#####End: Read spamd file(s) and input data into a hash of arrays for sorting.#####
#####Begin: Output of HTML file.#####
open(SPAMDHTMLSTATS, ">$spamdhtmlfile") or die ("Can't create file");
print SPAMDHTMLSTATS "<html><HEAD><TITLE>Pantz Spamdlog Stats</TITLE></HEAD><div align=\"center\">\n";
print SPAMDHTMLSTATS "<b><font size=\"4\">Pantz Spamdlog Stats</font></b><br>\n";
print SPAMDHTMLSTATS "Script run on: $Month-$Day-$Year $Hour:$Minute:$Second <br><br>\n";
print SPAMDHTMLSTATS "<TABLE BORDER=\"1\"><tr><td align=\"center\"><b>IP Address</b></td>
<td align=\"center\"><b>Hits</b></td><td align=\"center\"><b>Seconds</b></td></tr>\n";
# Loop thru the hash of arrays. Sort on the second value in the arrays. Print it.
for $ips ( sort { $spamd_hash {$b}[1] <=> $spamd_hash{$a}[1] } keys %spamd_hash ) {
print SPAMDHTMLSTATS "<tr><td align=\"center\">$ips</td>
<td align=\"center\">$spamd_hash{$ips}[1]</td>
<td align=\"center\">$spamd_hash{$ips}[0]</td></tr>\n";
$totalseconds += $spamd_hash{$ips}[0];
$totalhitcount += $spamd_hash{$ips}[1];
$totaluniquehosts++;
}
$avgpitmin = sprintf("%4.1f",($totalseconds/60)/$totalhitcount);
$avgnumhits = sprintf("%4.1f",$totalhitcount/($totaluniquehosts));
$totalpitmin = sprintf("%4.1f",$totalseconds/60);
$totalpithr = sprintf("%4.1f",($totalseconds/60)/60);
print SPAMDHTMLSTATS "<tr><td align=\"center\"><b>Totals:</b></td>
<td align=\"center\"><b>$totalhitcount</b></td><td align=\"center\">
<b>$totalpitmin Mins<br>$totalpithr Hrs</b></td></tr>";
print SPAMDHTMLSTATS "<tr><td align=\"center\"><b>Averages:</b></td>
<td align=\"center\"><b>$avgnumhits</b></td>
<td align=\"center\"><b>$avgpitmin Mins</b></td></tr>";
print SPAMDHTMLSTATS "</html>";
close(SPAMDHTMLSTATS);
Рекомендуемая литература