СЕРГЕЙ СУПРУНОВ
Запускаем spamd на FreeBSD
Бороться и искать,
Найти и не сдаваться!
Программа spamd, являющаяся частью OpenBSD, призвана блокировать нежелательную почту. Благодаря своей эффективности и оригинальному подходу к решению проблемы она была портирована на ряд других систем, включая FreeBSD. Об особенностях работы на этой платформе и пойдет речь в сегодняшней статье.
Найти и не сдаваться
Spamd – система фильтрации спама, использующая механизм «черного», «белого» и «серого» списков. Интересен алгоритм работы по серому списку: сообщение, отправитель которого не входит ни в белый, ни в черный списки, отклоняется с ошибкой 451 (временная ошибка, повторите попытку позже). И по реакции удаленной системы на эту вежливую просьбу принимается решение о занесении отправителя в белый список. В следующих подразделах будет описан принцип работы spamd, а необходимые для этого настройки рассмотрены далее в соответствующем разделе.
Работа в «нормальном» режиме
Spamd может быть сконфигурирован для работы в одном из двух режимов – «нормальном» и «сером» (greylisting mode). Схема работы spamd в нормальном режиме представлена на рис. 1.
Рисунок 1. Схема работы spamd в нормальном режиме
Соединение на порт 25 (SMTP) в зависимости от принадлежности отправителя черному списку пакетный фильтр pf либо пропускает как есть (на 25-й порт, прослушиваемый MTA) либо перенаправляет на вход spamd (по умолчанию используется порт TCP 8025, см. /etc/services). Типичный SMTP-диалог со spamd (для перенаправленных соединений) выглядит следующим образом:
220 test.ru ESMTP spamd IP-based SPAM blocker; Thu Jul 7 07:56:09 2005
HELO me
250 Hello, spam sender. Pleased to be wasting your time.
MAIL FROM: me@me.ru
250 You are about to try to deliver spam. Your time will be spent, for nothing.
RCPT TO: serg@test.ru
250 This is hurting you more than it is hurting me.
data
354 Enter spam, end with "." on a line by itself
Hello, spamd!
I test you!!!
.
450 SPAM. Blocked by me.
|
Ко всему прочему, каждый символ ответных сообщений выводится с задержкой в 1 секунду (по умолчанию, может быть изменено). То есть для соединений, попавших на вход spamd, стандартный диалог будет отрабатываться чрезвычайно медленно, и в итоге отправитель получает сообщение об ошибке. Таким образом, время соединения затягивается, спаммер должен полностью сформировать отправляемое сообщение, но в самый последний момент, буквально после завершающей точки, соединение разрывается. Причем в случае 450-го кода ответа оно обычно остается в очереди на отправку, и столь же безнадежные попытки могут повторяться неоднократно.
Работа в «сером» режиме
Будучи запущенным в greylisting mode (см. рис. 2), spamd для отправителей, занесенных в описанные в конфигурационном файле списки, работает так же, как и в нормальном режиме. Однако для соединений от неизвестных адресатов алгоритм работы меняется – они отклоняются с кодом 451, но задержка вывода символов диалога при этом не выполняется. Одновременно идентификационная информация соединения (IP-адрес источника, почтовые адреса отправителя и получателя) заносятся в базу данных /var/db/spamd с пометкой GREY. Так же фиксируется и время первой попытки. И в дальнейшем, если сообщение будет получено спустя время, равное значению параметра passtime (значение по умолчанию – 25 минут), то адрес отправителя заносится в белый список. Если же повторная попытка не будет выполнена в течение времени, указанному параметром greyexp (по умолчанию 4 часа), запись для данного соединения удаляется из /var/db/spamd.
Рисунок 2. Схема работы spamd в greylisting mode
Для адресов, занесенных в белый список, выполняется отслеживание соединений на 25-й порт (эту работу выполняет spamlogd), и если активности не наблюдалось в течение времени, равного значению параметра whiteexp (864 часа по умолчанию), то адрес удаляется из белого списка.
Перенаправление
За перенаправление почтового трафика, согласно спискам spamd, на порт 8025 отвечает пакетный фильтр pf (также портированный во FreeBSD из OpenBSD). Для этого в /etc/pf.conf нужно создать следующие записи:
table persist
rdr pass inet proto tcp from to any port smtp -> 1.2.3.25 port 8025
Обратите внимание на такую особенность. В man 8 spamd в качестве примера показано перенаправление на адрес 127.0.0.1. Однако если на вашей системе запущен еще и ipfw (что вполне вероятно), то для него по умолчанию имеются такие правила (см. /etc/rc.firewall):
${fwcmd} add 200 deny all from any to 127.0.0.0/8
${fwcmd} add 300 deny ip from 127.0.0.0/8 to any
В итоге пакеты, которые перенаправит pf, ipfw безжалостно заблокирует. Поэтому, на мой взгляд, лучше использовать адрес другого интерфейса (дополнительно можно указать его при запуске демона spamd с помощью ключа -b). И в любом случае нужно обеспечить прохождение пакетов на порт 8025 через все фильтры, работающие в системе (это особенно актуально в случае закрытого брандмауэра).
Таблица формируется утилитой spamd-setup, которая получает информацию из файла конфигурации /usr/local/etc/spamd.conf. Адреса, входящие в списки, помеченные в конфигурационном файле как black, будут занесены в указанную таблицу при запуске фильтра spamd. Подробнее использование списков будет рассмотрено позже при обсуждении конфигурации.
Естественно, приведенный выше шаблон ни в коем случае не является обязательным. Вы можете ограничиться перенаправлением только запросов, приходящих на конкретный адрес, пропускать нужные (например, собственные) адреса на 25-й порт до указанного правила (своеобразная альтернатива белым спискам) и т. д.
«Запятая» для размышления
Поскольку принцип действия spamd связан с задержкой сообщений, в ряде случаев это может оказаться критичным. Например, установка этого фильтра на сервере провайдера может породить массу возмущений со стороны пользователей, привыкших к мгновенной доставке сообщений. Поэтому spamd, особенно в «сером» режиме, больше пригоден для «внутреннего потребления», когда перечень легальных отправителей известен и может быть занесен в белый список, а остальную почту можно и задержать ненадолго.
Если вы, взвесив все «за» и «против», решили поставить фильтр spamd или по крайней мере глубже познакомиться с ним, то продолжим.
Установить и не запутаться
Инсталляция из системы портов никаких сложностей не вызывает. Все традиционно:
# cd /usr/ports/mail/spamd; make install
Теперь осталось в файле /etc/rc.conf включить поддержку spamd и пакетного фильтра pf (если он не был запущен ранее):
pf_enable="YES"
pf_flags=""
pflog_enable="YES"
pfspamd_enable="YES"
pfspamd_flags="-v"
Нужно обратить внимание вот на что: файл с именем spamd уже может находиться в вашей системе. Это гордое имя носит также и демон Spamassassin, и если вы устанавливали этот пакет, то соответствующий файл будет лежать в /usr/local/bin/ (при условии, что не менялись стандартные пути). Однако беспокоиться по этому поводу не стоит – наш spamd устанавливается в другое место, и перезаписи файлов произойти не должно.
Чтобы было проще разобраться, что к чему относится, приведу сравнительную таблицу:
Таблица 1. Расположение компонентов Spamassasin и Spamd
|
Spamassassin
|
Spamd
|
Исполняемый файл spamd
|
/usr/local/bin/spamd
|
/usr/local/libexec/spamd
|
Конфигурационные файлы
|
/usr/local/etc/mail/spamassassin/*
/usr/local/share/spamassassin/*
|
/usr/local/etc/spamd.conf
|
Сценарий автозапуска
|
/usr/local/rc.d/sa-spamd.sh
|
/usr/local/rc.d/pfspamd.sh
|
PID-файл
|
/var/run/spamd/spamd.pid
|
Нет
|
Страница руководства
|
man 1 spamd
|
man 8 spamd
|
Небольшая проблема возникает при «ручном» управлении фильтром с использованием сценария из /usr/local/etc/rc.d: поскольку spamd не использует PID-файл, то при запуске соответствующего скрипта с ключом «start» выполняется проверка по имени запущенных процессов. Так как при этом обнаруживаются процессы, принадлежащие spamassassin, то запуск не выполняется:
# ./pfspamd.sh start
pfspamd already running? (pid=26357 26359 26361 26363 26366). |
Обойти это можно, запуская pfspamd.sh с ключом «faststart» вместо «start». При этом проверка того, запущен ли соответствующий процесс, выполняться не будет, эта забота ложится на плечи администратора.
При автоматическом запуске во время загрузки системы первым стартует pfspamd.sh (rc-сценарии исполняются в порядке, определяемом утилитой rcorder, но в данном случае требования к порядку запуска у рассматриваемых скриптов одинаковы, и они будут выполняться в алфавитном порядке, так что pfspamd.sh имеет преимущество). Поскольку запускаемый вторым скрипт sa-spamd.sh ориентируется по своему PID-файлу, то и его старт проходит нормально.
Настроить и запустить
Настройки белых и черных списков для spamd сосредоточены в файле /usr/local/etc/spamd.conf. Сразу после установки в указанном каталоге будет находиться только файл spamd.conf.sample, который следует переименовать в spamd.conf и подправить под собственные нужды. Кроме того, потребуется внести ряд изменений в файл /etc/pf.conf (конфигурационный файл пакетного фильтра pf). Также нужно знать ключи запуска spamd, поскольку именно ими определяется режим работы демона и значения используемых параметров.
Параметры spamd.conf
Данный конфигурационный файл используется утилитой spamd-setup для первоначальной настройки таблиц pf при запуске spamd. Формат spamd.conf достаточно прост и соответствует getcap(3). В нем обязательно должна присутствовать запись all:
all:
:spamhaus:blacklist:whitelist:
В этой записи перечислены используемые списки в порядке их применения. В данном случае описаны следующие три списка:
spamhaus:
:black:
:msg="SPAM. Your address %A is in the Spamhaus Block List
See http://www.spamhaus.org/sbl and
http://www.abuse.net/sbl.phtml?IP=%A for more details":
:method=http:
:file=www.openbsd.org/spamd/SBL.cidr.gz:
Данный список для блокировки нежелательной почты использует информацию о спаммерах, собираемую сайтом spamhaus.org (для загрузки по http используется файл, сохраненный на сервере openbsd.org).
blacklist:
:black:
:msg="SPAM. Blocked by me":
:file=/usr/local/etc/spamd/blacklist.txt:
Эта запись указывает на необходимость загрузить в черный список адреса из указанного локального файла. Поскольку этот метод используется по умолчанию, ключ «method» опущен.
whitelist:
:white:
:file=/usr/local/etc/spamd/whitelist.txt:
А это белый список. Параметр «msg» здесь за ненадобностью не используется. Если адрес отправителя занесен в указанный файл, то он будет исключен из предыдущего черного списка, если там окажется.
На основании данного конфигурационного файла spamd-setup формирует черные списки. При этом адреса в них упорядочиваются по возрастанию, исключаются дублирования и пересечения подсетей так, чтобы любой адрес был представлен только в единственном экземпляре. Адреса, присутствующие в белом списке, исключаются из предыдущего черного (и только из него). Если «белый» адрес должен быть исключен из нескольких черных списков, в секции «all» соответствующий белый список следует указать после каждого такого черного списка.
Сформированные списки утилита spamd-setup загружает в таблицу фильтра pf (используя команду pfctl), а также отправляет их на управляющий порт (tcp/8026) демону spamd.
В ходе тестирования было выявлено интересное поведение демона (используемая версия программы – 3.7) – то ли из-за ошибки разработчика, то ли по иной недосягаемой для моего понимания причине spamd при обработке данных, поступающих на порт 8026, не воспринимает последний (самый большой) адрес. Поскольку в таблицу он заносится нормально, то перенаправление на порт 8025 его соединений выполняется, но spamd как «черный» данный адрес не воспринимает, помечая его как серый (GREY) и возвращая вместо ответа 450 или 550, определяемого ключами запуска, код 451 «Временная ошибка». Но так как на MTA такое соединение все равно не проходит, на корректность работы фильтра эта ошибка практически не влияет.
Несколько слов нужно сказать о формате списков. Это обычные текстовые файлы (могут быть упакованы утилитой gzip), в которые заносятся черные или белые адреса, интервалы адресов или подсети, по одному в каждой строке. Допускаются комментарии, начинающиеся с символа «#». После адреса могут содержаться любые пометки – при обработке используется только первая часть строки, соответствующая одному из указанных форматов. Например, файл списка может выглядеть так:
# Пример черного списка
192.168.0.5 # Отдельный IP-адрес
10.0.0.1 – 10.0.2.255 # Диапазон адресов наглых спаммеров!!!
5.6.7.0/24 # Так можно задать подсеть
# Попытка обмануть spamd:
255.255.255.254
Последняя строчка может быть использована для решения описанной выше проблемы. Поскольку при сортировке данный адрес окажется последним (независимо от его места в файле списка), то именно он не будет воспринят демоном spamd. Все остальные адреса нормально будут обработаны как «черные». Однако не забывайте, что такой «завершающий» адрес все равно попадет в и будет перенаправляться.
Наблюдать за процессом заполнения черных списков можно, запустив spamd-setup с ключом -d:
# /usr/local/sbin/spamd-setup –d
Getting http://www.openbsd.org/spamd/spews_list_level1.txt.gz
blacklist spews1 18541 entries
Getting http://www.openbsd.org/spamd/spews_list_level2.txt.gz
blacklist spews2 22641 entries
Getting http://www.openbsd.org/spamd/chinacidr.txt.gz
blacklist china 321 entries
Getting http://www.openbsd.org/spamd/koreacidr.txt.gz
blacklist korea 162 entries
blacklist myblack 1 entries
whitelist mywhite 4 entries
|
Не забывайте выполнять spamd-setup каждый раз после перезапуска pf, чтобы вновь заполнить таблицу . Так же полезно занести вызов этой утилиты в crontab, чтобы периодически (например, раз в сутки) обновлять внешние черные списки.
Настройка журналирования
Демон spamd пишет свои сообщения в syslog. Чтобы собрать все сообщения в одно место, удобно направить их в отдельный файл, для чего в /etc/syslog.conf поместим строки:
!spamd
*.* /var/log/spamd.log
Правда, при такой настройке Spamassassin (если он запущен) тоже будет использовать этот файл. Поскольку syslogd не создает отсутствующие файлы, то это придется сделать вручную, после чего нужно отправить сигнал HUP процессу syslogd:
# touch /var/log/spamd.log
# kill –HUP `cat /var/run/syslog.pid`
Теперь сообщения от демона spamd будут собираться в файле /var/log/spamd.log. На стадии отладки для повышения информативности можно будет запускать spamd с ключом -v.
Типичный вывод выглядит следующим образом:
Jul 7 07:39:49 konst spamd[23]: 1.2.3.4: connected (2/2), lists: korea
Jul 7 07:39:55 konst spamd[23]: (BLACK) 1.2.3.4: <br9@tlcm.ru> -> <kp@test.ru>
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: From: =?Windows-1251?B?gg6vPv4O3o5ewu?=
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: To: kp@test.ru
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Subject: =?Windows-1251?B?wg6vPv4O3o5ewu?=
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Body: <head>
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Body: <title></title>
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Body: </head>
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Body: <body bgcolor="#FFFFFF">
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Body: <p align="center">
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: Body: <p align="right">
Jul 7 07:39:58 konst spamd[23]: 1.2.3.4: disconnected after 9 seconds. lists: korea
|
То есть здесь можно найти информацию о времени установления и разрыва соединения, а также об отправителе и получателе сообщения. Кроме того, в лог-файл (в режиме подробного вывода, настраиваемого опцией -v) выводятся заголовок и несколько первых строк тела сообщения.
Если для протоколирования работы spamd вы используете отдельный файл, то не забудьте добавить для него правило ротации в /etc/newsyslog.conf.
Нормальный режим
В нормальном режиме spamd используется только для задержки спам-трафика, поэтому перенаправление выполняется лишь для адресов, занесенных в черный список. Белые списки используются для удаления адресов из черных списков. Например, рассмотрим такой конфигурационный файл:
all:\
:blacklist:
blacklist:\
:black:\
:msg="SPAM. Blocked by me":\
:file=/usr/local/etc/spamd/blacklist.txt:
В данном случае в таблицу <spamd> фильтра pf заносятся все адреса из файла blacklist.txt. Все остальные источники будут пропущены на реальный MTA. Если же добавить белый список:
all:\
:blacklist:whitelist:
blacklist:\
:black:\
:msg="SPAM. Blocked by me":\
:file=/usr/local/etc/spamd/blacklist.txt:
whitelist:\
:white:\
:file=/usr/local/etc/spamd/whitelist.txt:
то в таблицу попадет содержимое blacklist.txt за исключением адресов, перечисленных в whitelist.txt. Причем таким свойством «вычитания» обладает только белый список, приведенный в строке «all» непосредственно после имени черного.
«Серый» режим
В сером режиме, как было показано выше, белый список применяется явно, в то время как адреса, не представленные ни в одном из списков, получают серый оттенок и обрабатываются особым образом. Для реализации этого, во-первых, требуется дополнительная таблица и правило перенаправления в /etc/pf.conf:
table persist
rdr pass inet proto tcp from ! to any port smtp -> 1.2.3.25 port spamd
В итоге соединения, источник которых не включен в , тоже будут перенаправляться на порт 8025. За формирование белого списка теперь отвечает сам spamd, динамически добавляя нужные адреса в таблицу . За черный список по-прежнему отвечает spamd-setup.
Обратите внимание, что адреса, занесенные в белые списки spamd.conf, лишь исключаются из черных. То есть spamd будет воспринимать их как серые.
Во-вторых, чтобы spamd запустился в сером режиме, используется ключ «-g», который нужно указать в файле /etc/rc.d в строке pfspamd_flags:
pfspamd_flags="-g –G 25:4:864 -v"
Необязательный ключ «-G» задает временные интервалы соответственно для pastime, greyexp и whiteexp. Здесь же можно добавить ключ «-v», чтобы на период отладки получать более подробную информацию о работе фильтра.
Возможно, я что-то упустил в процессе настройки, но при включении серого режима на экран стали выводиться такие сообщения об ошибке:
pfctl : /dev/fd/7: No such file or directory |
Добиться нормальной работы удалось после ручного монтирования файловой системы дескрипторов fdescfs (см. man 5 fdescfs):
# mount_fdescfs 7 /dev/fd/
Как видно на представленном ниже листинге, spamd в «сером» режиме запускает еще два процесса – отвечающий за обновление белого списка (процесс 6017) и за обновление базы /var/db/spamd (процесс 6020):
6017 ?? Ss 0:00,02 spamd: (pf update) (spamd)
6018 ?? S 0:00,07 /usr/local/libexec/spamd -v -g -G5:1:2
6020 ?? S 0:00,00 spamd: (/var/db/spamd update) (spamd)
|
Файл /var/db/spamd, хранящий информацию о поступивших запросах и их дальнейшей судьбе, создается автоматически, когда spamd запускается с ключом -g. Посмотреть состав этой базы можно, если выполнить команду spamdb без параметров:
# /usr/local/sbin/spamdb
GREY|1.2.3.4|||1120715668|1120719268|1120719268|1|0
GREY|5.6.7.8|||1120716752|1120720352|1120720352|1|0
WHITE|10.0.0.203|||1120715625|1120717099|1120724330|2|0
|
Поля в каждой строчке означают следующее (слева направо): тип записи (GREY, WHITE и т. п.), IP-адрес источника, адрес отправителя, адрес получателя, время первой попытки, время перехода адреса из статуса GREY в статус WHITE, время удаления записи из базы, количество заблокированных попыток, количество пропущенных соединений.
Если повторная попытка соединения будет выполнена спустя интервал pastime, но до истечения периода greyexp, адрес заносится в таблицу , и в дальнейшем соответствующие соединения пропускаются на MTA. Состав таблицы можно посмотреть следующей командой:
# pfctl -t spamd-white –Tshow
С помощью команды /usr/local/sbin/spamdb можно добавлять в базу данных новые «белые» адреса либо удалять имеющиеся:
# /usr/local/sbin/spamdb
GREY|1.2.3.4|||1120715668|1120719268|1120719268|1|0
GREY|5.6.7.8|||1120716752|1120720352|1120720352|1|0
WHITE|10.0.0.203|||1120715625|1120717099|1120724330|2|0
|
root# /usr/local/sbin/spamdb -d 10.0.0.203
root# /usr/local/sbin/spamdb
GREY|1.2.3.4|||1120715668|1120719268|1120719268|1|0
GREY|5.6.7.8|||1120716752|1120720352|1120720352|1|0
|
root# /usr/local/sbin/spamdb -a 10.161.193.253
root# /usr/local/sbin/spamdb
WHITE|10.0.0.203|||1120730510|1120730510|1123840910|1|0
GREY|1.2.3.4|||1120715668|1120719268|1120719268|1|0
GREY|5.6.7.8|||1120716752|1120720352|1120720352|1|0
|
Механизм «greylisting mode», конечно, не дает абсолютной гарантии, что спам не попадет в ящики пользователей. В этом режиме лишь предпринимается попытка отсеять случайные соединения (для которых не будут выполняться повторные попытки) либо слишком частые попытки «протолкнуть» вам свое письмо.
Используем ловушки
При работе в «сером» режиме возможно использование так называемых ловушек – фиктивных адресов электронной почты, которые в вашей системе отсутствуют. Если на такой адрес будет получено письмо, его отправитель автоматически заносится в черный список сроком на 24 часа. Хороший эффект дает использование в качестве ловушки популярных у спаммеров адресов (alex, max, oao, sales и др.). Подобная ловушка заносится в базу /var/db/spamd следующей командой:
# /usr/local/sbin/spamdb -T -a ""
# /usr/local/sbin/spamdb -t -a 10.0.0.225
# /usr/local/sbin/spamdb | grep TRAP
SPAMTRAP|max@test.ru
TRAPPED|10.0.0.225|1120817623
|
Ключ -T позволяет добавить ловушку. Адреса, с которых будут выполняться попытки доставить почту на адрес ловушки, заносятся в базу как TRAPPED и обрабатываются как принадлежащие черному списку, пока не пройдут сутки с момента последней попытки соединения. Через 24 часа адрес удаляется из базы и вновь обрабатывается как «серый». С помощью ключа -t можно вручную добавить в базу адрес как «пойманный», как это показано для адреса 10.0.0.225.
Подробнее о ключах запуска
Spamd помимо ключей g, G, v, которые нам уже встречались, может быть запущен еще с несколькими полезными опциями:
- -b: указывается IP-адрес интерфейса, на котором spamd будет ожидать входящие соединения (по умолчанию прослушиваются все имеющиеся интерфейсы).
- -s: задает время задержки перед выводом каждого символа в диалоге с отправителем, занесенным в один из черных списков. По умолчанию задано значение, равное 1 секунде.
- -4 или -5: код ответа спаммеру, 450 (по умолчанию) или 550 соответственно.
- -c: максимальное число одновременных подключений.
- -B: максимальное число одновременных подключений для адресов, занесенных в черный список.
- -n: строка, выводимая в баннере приветствия.
- -d: запущенный с этим ключом spamd не переключается в фоновый режим, что позволяет наблюдать на экране то, как он работает.
Поскольку spamd не имеет конфигурационного файла (напомню, что spamd.conf обрабатывается утилитой spamd-setup), то единственный способ настроить его работу – использование ключей запуска.
Доработать и …
Пожалуй, одного инструмента для комфортной работы со spamd не хватает – при первоначальном запуске в сером режиме адреса разрешенных отправителей (например, удаленных сотрудников, адреса главного офиса и т. д.) приходится заносить в таблицу вручную. Попробуем устранить это неудобство подручными средствами, разработав на Python несложный скрипт, который будет заносить белые адреса в базу /var/db/spamd из текстового файла:
Листинг 1. Сценарий a2w.py
#!/usr/local/bin/python
import sys, os
def Usage():
print 'Usage: a2w.py filename'
sys.exit(-1)
# Подпрограмма «разворачивает» подсеть в список адресов
def Expand(subnet):
global whitelist
if subnet.find(‘/’) == -1:
subnet = subnet + '/32'
netaddr, masklen = subnet.split('/')
masklen = int(masklen)
# Если ошибка – оставляем запись как есть
if masklen < 1 or masklen > 32:
whitelist.append(subnet)
return
# Здесь используется синтаксис «расширенного списка» – результат будет получен как список значений функции int
# для каждого элемента в списке, возвращаемом функцией split
o1, o2, o3, o4 = [int(o) for o in netaddr.split('.')]
for i in range(0, 2 ** (32 - masklen + 1)):
addr = '%d.%d.%d.%d' % (o1, o2, o3, o4)
whitelist.append(addr)
o4 += 1
if o4 == 256:
o3 += 1; o4 = 0
if o3 == 256:
o2 += 1; o3 = 0
if o2 == 256:
o1 += 1; o2 = 0
# Если нельзя, но очень хочется – то можно!
# (Это про несколько операторов в одной строке…)
#----------------------------------------------
if len(sys.argv) != 2:
Usage()
DEBUG = 1
errcnt = 0
spamdbcmd = '/usr/local/sbin/spamdb'
filelist = open(sys.argv[1], 'r').readlines()
whitelist = []
for line in filelist:
Expand(line[:-1])
for addr in whitelist:
cmd = spamdbcmd + ' -a ' + addr
# Запятая после аргументов команды print оставляет курсор на текущей строке
if DEBUG:
print 'Try: ' + cmd,
# Функция os.system вернет 0, если указанная как аргумент команда будет выполнена успешно
err = os.system(cmd)
if err:
errcnt += 1
if DEBUG:
print 'Failed'
else:
if DEBUG:
print 'ok'
if errcnt:
print 'WARNING: executed with errors (see above)'
Приведенный сценарий считывает данные из текстового файла, передаваемого как аргумент командной строки, и заносит их в базу spamdb, используя команду /var/local/sbin/spamdb -a. Формат текстового файла не допускает комментариев, пустых строк и т. д. Он может содержать только IP-адреса или подсети в формате CIDR, по одной записи в строке:
# cat wl.txt
10.10.29.192/29
1.2.3.4/33
|
Подсети, определяемые по наличию символа «/», функцией Expand «разворачиваются» в список отдельных IP-адресов whitelist, который затем поэлементно передается программе spamdb. Если длина маски задана неправильно, то сценарий оставляет запись как есть, возлагая обработку ошибки на утилиту spamdb (вторая запись в файле wl.txt демонстрирует поведение в этом случае). Если отладка включена (переменная DEBUG не равна 0), то каждая попытка и ее результат будут отображаться на экране:
# ./a2w.py wl.txt
Try: /usr/local/sbin/spamdb -a 10.20.29.192 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.193 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.194 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.195 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.196 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.197 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.198 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.199 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.200 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.201 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.202 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.203 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.204 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.205 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.206 ok
Try: /usr/local/sbin/spamdb -a 10.20.29.207 ok
spamdb: invalid ip address 1.2.3.4/33
Try: /usr/local/sbin/spamdb -a 1.2.3.4/33 Failed
WARNING: executed with errors (see above)
|
После выполнения сценария можно убедиться, что соответствующие адреса добавлены в базу как «белые»:
# /usr/local/sbin/spamdb | grep WHITE
WHITE|10.20.29.192|||1120801435|1120801442|1123911842|1|1
WHITE|10.20.29.193|||1120801435|1120801442|1123911842|1|1
WHITE|10.20.29.194|||1120801435|1120801442|1123911842|1|1
WHITE|10.20.29.195|||1120801435|1120801442|1123911842|1|1
WHITE|10.20.29.196|||1120801435|1120801442|1123911842|1|1
WHITE|10.20.29.197|||1120801435|1120801442|1123911842|1|1
WHITE|10.20.29.198|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.199|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.200|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.201|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.202|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.203|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.204|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.205|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.206|||1120801436|1120801442|1123911842|1|1
WHITE|10.20.29.207|||1120801436|1120801442|1123911842|1|1
|
Кстати, аналогично можно поступить и с ловушками, если вы планируете создать их достаточно большое количество. Эту задачу оставлю вам в качестве упражнения.
… поставить точку
Итак, мы рассмотрели работу пакета spamd в системе FreeBSD. Используемый им оригинальный подход к решению проблемы спама в ряде случаев оказывается весьма эффективным. К тому же можно порадоваться, что теперь не только спаммеры могут портить нам жизнь – есть инструмент, с помощью которого можно ответить им тем же.