четверг, 26 июля 2007 г.

Web анонсы

Провайдер сегодня порадовал. Принудительными анонсами. Открываешь страницу с произвольным адресом. Но самой этой страницы не видишь, а происходит перенаправление на внутренний сервер с рекламой. Выглядит это так:

Остается только догадываться что будет с различными автоматизированными системами, которые в своей работе используют web запросы.

Slackware 12

Наконец-то добрался до Slackware 12. Как обычно, сначала любую новую операционую систему я пробую устанавливать в виртуальной машине. Инсталяция прошла гладко, ни на шаг не отступая от классической схемы установки Slackware — консоль, разбиение диска с помощью fdisk, выбор пакетов для установки из списка. Как обычно выбираю абсолютный минимум необходимых пакетов. Отметил, что теперь по умолчанию предлагается форматировать разделы диска в ext3, вместо raiserfs как было раньше. Порадовало наличие пакета openvpn. До 12-ой версии Slackware похоже был последним дистрибутивом, содержащим веб сервер apache1. Теперь он заменен сразу на apache2.2!, кто-то наверное обрадуется, а мне немного грустно, т.к. возможностей apache1 мне хватало абсолютно.

Для каждой виртуальной машины я выделяю 48Мб памяти. Для Slackware с версий 9.1 по 11 этого вполне хватало не только для загрузки, но и для адекватной работы в качестве девелоперской машины LAMP сервером, естественно без иксов. Но вот загружается Slackware 12 и первое впечатление — дааа, потяжелела слакварь, курсор в консоле еле ворочается, память занята вся и ещё немало подкачки отъела.

Однако проблема довольно быстро решается:

  1. Отключаем появившиеся в Слаке новомодные сервисы, необходимые только для десктопа. Для этого снимаем атрибут исполняемого файла с:

    • /etc/rc.d/rc.hald
    • /etc/rc.d/rc.messagebus
    • /etc/rc.d/rc.udev
  2. В /etc/rc.d/rc.modules отключаем загрузку ненужных модулей ядра, а именно:

    # /sbin/modprobe psmouse proto=imps
    # /sbin/modprobe pcspkr
    # /sbin/modprobe -q parport_pc 2> /dev/null
    # /sbin/modprobe agpgart 2> /dev/null
    # /sbin/modprobe capability

    После этого в памяти оставался ещё не нужный нам модуль ядра ipv6. Его отключаем добавлением следующих строчек в /etc/modprobe.d/blacklist:

    alias net-pf-10 off
    blacklist ipv6
  3. Многие знают, что Slackware 12, тоже одним из последних, перешел на ядро 2.6. Но не все знают, что теперь в Slackware 12 есть две сборки ядра, называемые huge и generic. По умолчанию грузится huge, где большинство модулей вкомпилены в ядро. Так не возникают проблемы при загрузкой с разных файловых систем, но это ядро занимает много памяти. Чтобы переключится на generic ядро скорее вам всего нужно будет собрать initrd, содержащий как минимум модуль ядра для корневой файловой системы. Краткие объяснения и инструкция содержатся в файле /boot/README.initrd. В моём случае понадобилось выполнить следующую команду:

    mkinitrd -c -k 2.6.21.5-smp -m ext3

    Добавляем пункт загрузки с generic ядра в меню lilo, для этого вставляем строки в файл /etc/lilo.conf:

    image = /boot/vmlinuz-generic-smp-2.6.21.5-smp
      initrd = /boot/initrd.gz
      root = /dev/XXXN
      label = Linux-generic
      read-only

После этих действий система стала вести себя более отзывчиво :-). 48 Мб опять хватает. В общем я доволен. Мы получили дистрибутив, который с одной стороны идет в ногу со временем, включающий последние достижения Open Source, обновленные версии всех программ. С другой стороны Slackware строго придерживается собственных традиций, устанавливаются оригинальные версии программ, без патчей. Позволяется максимально возможную гибкость в настройке системы. В общем, я всё больше убеждаюсь, что Slacware лучшая ОС для серверных решений.

понедельник, 16 июля 2007 г.

Фильтрация спама для Qmail c помощью SpamAssassin

Все написанное производилось для Slackware 9.1. Описание установки и настройки Qmail, а также описание установки SpamAssassin не приводится. Почта пользователей сервера myserver.ru хранится в домашних каталогах пользователей в Maildir формате.

Спам — достал. Способов борьбы с ним тьма, но что-то же выбрать надо. Что мне понравилось в SpamAssassin, это отсутствие необходимости постоянно в ручную обучать его новому спаму, чтобы он работал эффективно. То есть, при желании это можно делать, но пользователей обучить нереально, а сисадмину и так есть чем занятся :-).

Для работы SpamAssassin использует огромную базу правил. Каждому правилу назначается определенный вес. При проверке письма веса всех «сработавших» правил суммируются. Если сумма превысила пороговое значение, письмо помечается как спам. База всех правил постоянно пополняется, весовые коэффициенты уточняются. SpamAssassin предоставляет утилиту для обновления базы правил, которую можно запускать в автоматическом режиме по расписанию.

Есть два способа обращаться к SpamAssasin:

  1. в режиме утилиты командной строки — spamassasin,
  2. в режиме клиента spamc для демона spamd.

Второй вариант работает быстрее, т.к. не тратится время на запуск и инициализацию программы. Однако расходует больше памяти, т.к. демон должен быть постоянно запущен. Как показала практика, SpamAssassin достаточно тяжел в работе, на принятие решения по одному письму уходит от 2-х до 7 секунд работы программы. А памяти на серверах обычно много и она дешева. Поэтому используем второй вариант. Для автоматического запуска демона spamd при загрузке сервера прописываем в файле /etc/rc.d/rc.M строчки:

# Start the SpamAssasin daemon:
if [ -x /etc/rc.d/rc.spamd ]; then
  /etc/rc.d/rc.spamd start
fi

Вики SpamAssasin предлагает три способа интеграции с qmail:

  1. Через программу Simscan глобально на этапе приема письма по smtp;
  2. Через программу qmail-scanner глобально на этапе пересылки/доставки письма;
  3. Через скрипт ifspamh и редактирование файла ~/.qmail для индивидуального почтового ящика на этапе локальной доставки письма;

Используем третий способ, как самый безопасный для экспериментов на работающем сервере. Устанавливаем скрипт ifspamh:

cd /usr/local/bin
wget http://www.gbnet.net/~jrg/qmail/ifspamh/ifspamh
chmod +x ifspamh

Скрипт ifspamh «из коробки» не заработал, пришлось немного подпилить. Вместо оболочки ksh, которую я не устанавливал прописал запуск из bash. На работоспособность скрипта это не повлияло. Подправил пути поиска утилит spamc, forward (входит в qmail) и 822field. Утилита 822field входит в состав пакета mess822. Мне повезло, пакет mess822 для Slackware 9.1 был на linuxpackages.net. А если бы не было, так не беда — сам бы собрал, просто ленив я стал...

Для каждого пользователя, которому нужна фильтрация спама редактируем файл ~/.qmail:

|/usr/local/bin/ifspamh spam@myserver.ru
./Maildir/

Теперь весь обнаруженный спам будет пересылаться на ящик spam@myserver.ru, эдакий спамоотстойник сервера. Доставки в локальный ящик не будет. Письма не удаляются, администратор всегда сможет найти ложно отфильтрованное письмо в отстойнике. Теперь проверим работу обновления базы правил SpamAssassin, для этого используется утилита sa-update. Запустим её без параметров, если все пройдёт успешно, то в каталоге /var/lib/spamassassin/<version>/ появятся обновленные базы правил. Чтобы обновления вступили в силу, демон spamd необходимо перезапустить. Прописать запуск sa-update в автоматическом режиме по расписанию я пока не решился. Но тем не менее crontab изменить пришлось:

# 0 2 * * * sa-update && /etc/rc.d/rc.spamd restart
0 3 * * * find ~spam/Maildir -ctime +31 -type f -exec rm {} \;

Как вы заметили, я добавил очистку ящика spam@myserver.ru, чтобы этот отстойник не переполнился. Если письмо в течении месяца никому так и не понадобилось, то его можно спокойно удалить.

За прошедший (не очень продолжительный) период работы не было ни одного ложного срабатывания. Эффективность обнаружения спама около 97%. Всё.

пятница, 13 июля 2007 г.

Про ФСБ

Повествовательный рассказ без выводов и нравоучений про ФСБ.

Однажды, в начале лета 2006 года, мне позвонил весьма отдаленный знакомый:

— Меня спрашивали про опытного компьютерщика, что-то связанное с компьютерной безопасностью. Мне, кроме тебя, что-то и в голову никто не приходит. Если тебе интересно, могу дать твой телефон тому человеку.

С одной стороны я очень удивился: да я вроде компьютерщик до мозга костей, опытный или нет, это уж не мне судить. Но компьютерная безопасность — абсолютно не мой профиль. С другой стороны, в нашем маленьком провинциальном городе я не знаю никого, кто был бы исключительно специалистом по компьютерной безопасности. Да и сложно представить себе о чем идет речь, пока лично не пообщался. К тому же, я уже начал задумываться, что родная (на тот момент) контора платит мало и перспектив никаких. В случае чего и подработка лишней не будет, так что я согласился.

Дня через два позвонил, назовем его пока Джеймс Бонд, предложил встретится в кафешке. Так и сделали. Бонд оказался молодым человеком, не отталкивающей наружности. Далее так написали бы в шпионском романе: «Бонд выбрал столик с хорошим обзором всего кафе и входной двери. При этом любой входящий в зал, оказывался повернут в пол оборота, так что его можно было хорошо рассмотреть, оставаясь самому незамеченным. Бонд предложил мне сесть к стене, так что я фактически оказался заперт за столом, не имея возможности встать и уйти, пока он сам меня не выпустит». Заказали мы, к сожалению, не по бокалу любимого напитка киногероя — мартини, а по пиву и Бонд начал разговор:

— Ты наверное в детстве много читал?

Я ответил утвердительно.

— Наверное читал «Щит и меч»?

Я удивился, но чтобы не грешить против истины, опять ответил утвердительно. После аналогичного вопроса про «Семнадцать мгновений весны» начался пространный рассказ о том, что отечество в опасности, НАТО не дремлет, загнивающие буржуи окружают. Например, недавно поймали китайцев, фотографирующих расположение наших военных частей. Или с авиационного завода пытались продать какую-то документацию. Я решаю прервать этот поток сознания:

— А ты собственно кто?

Не говоря ни слова Бонд достает корочку удостоверения и предъявляет её мне. Разоблачается таким образом в лейтенанта ФСБ Антона Митина. Я начинаю себя чувствовать неуютно. Тем временем, пространный рассказ продолжается. Оказывается, с его слов, Митин — главный специалист ФСБ по информационной безопасности в городе. Все остальные уже в возрасте, он единственный кто соображает. Информационные преступления на каждом шагу, а его «служба и опасна и трудна», он не успевает в одиночку с ними справляться. Рисуется образ печального рыцаря, преданного делу короны. Снова мне приходится прервать его:

— Хорошо, а что ты хочешь от меня?

Извлекается листок со списком так называемых honeypot систем, палец тыкается в одну программу из списка и мне предлагается где-нибудь найти и взломать её. Я отвечаю:

— Это тянет на статью «получение незаконного доступа к программам или базам данных» и/или «незаконная модификацию программ или баз данных». До 2-х лет, если не ошибаюсь, в формулировках и сроках ты лучше разбираешься.

— Вот ты повернул! Мне такое даже и в голову бы не пришло, тем более что привлечь по этой статье нереально. Хорошо давай мы сами её найдем, тебе только взломать останется. Ты же, например, Windows взломанным пользуешься?

— У меня на рабочем и на домашнем компьютере нет ни Windows, ни одной другой краденной программы.

Митин-Бонд посмотрел на меня с недоверием, но ничего не возразил. Начал расспрашивать меня о моей работе. Когда разговор, коснулся Open Source глаза его вспыхнули и он произнес: «Да это же транснациональные организованные сообщества!». Кроме того хвалился, что поддерживает постоянную связь с начальником безопасности моей конторы, бывшим КГБистом, и уже «пробил» всё про меня. Потом произнес:

— У нас не хватает сведений об информационных преступления. Я же один на весь город. Мог бы ты, если где-то что-то краем уха услышишь, сообщать мне? Или вдруг в англоязычных рассылках чего промелькнёт. Например, вдруг кто-нибудь из участников работает в Боинге, а Боинг ведь на наш авиазавод моторы поставлять будет...

Тут я почувствовал себя гадко, по-настоящему гадко, как будто в говно случайно наступил. То что меня будут вербовать в качестве стукача, я никак не ожидал:

— Пока сохраняется хоть малейшая иллюзия свободы моего выбора, я этого делать не буду.

— Никто насильно тебя не заставляет. Просто подумай, какую пользу ты можешь принести своей Родине. И кроме того, если информация окажется ценной, она хорошо оплачивается.

— Нет. На этом я хотел бы завершить наш разговор.

— Пожалуйста.

На этом мы распрощались. Митин взял с меня обещание никому не распространяться об этом разговоре. Больше, слава богу, я его не видел, и надеюсь никогда не увижу.

пятница, 6 июля 2007 г.

Генерация Excel документов на perl

Описание задачи. Имеется программная телефонная станция на базе asterisk. Журнал звонков этой телефонной станции ведется в базе данных mysql. Названия полей таблицы соответствуют названиям полей CDR (Call Detail Record). Возникла необходимость в доступе к этому журналу для менеджеров. Менеджеры, братья наши меньшие, абсолютно не очарованы таблицами баз данных, SQL для них чужд. Зато документы в формате Excel милы их сердцам. Поэтому напишем perl скрипт для генерации Excel отчета из базы данных. Для создания excel файлов воспользуемся perl модулем Excel::Template, позволяющем, как видно из названия, создавать .xls файлы на основе xml шаблона. Вы ведь не хотите менять программу каждый раз, когда нужно будет увеличить размер шрифта или поменять местами колонки в отчете? Сначала приведем содержимое файла шаблона report.xml:
<workbook>
 <worksheet name="report">
   <format align="center" valign="vcenter" bold="bold" border="2">
     <row>
       <cell width="15">Откуда</cell>
       <cell width="15">Куда</cell>
       <cell width="15">Начало</cell>
       <cell width="15">Длительность</cell>
     </row>
   </format>

   <format border="1">
     <loop name="report_data">
       <row>
         <cell><var name="src" /></cell>
         <cell><var name="dst" /></cell>
         <cell><var name="start" /></cell>
         <cell><var name="billsec" /></cell>
       </row>
     </loop>
   </format>
 </worksheet>
</workbook>
В данном шаблоне описывается excel документ, содержащий один лист с данными. На этом листе первая строка содержит заголовки 4-х колонок отчета: «Откуда» — номер вызывающего абонента, «Куда» — номер вызываемого абонента, «Начало» — время начала звонка, «Длительность» — длительность звонка. Остальные строки заполняются данными отчета по количеству записей в нём. Подробное описание всех тегов шаблона присутствует в документации perl модуля Excel::Template. Теперь сам скрипт report.pl:
#!/usr/bin/perl -w -t
use strict;

use DateTime;
use DBI;
use Excel::Template;

# подключение к базе данных
my $dsn    = 'dbi:mysql:database=...;host=...';
my $dbuser = '...';
my $dbpass = '...';
my $dbh    = DBI->connect( $dsn, $dbuser, $dbpass, { RaiseError => 1 } );

# задаем период формирования отчета
my $period_begin = DateTime->new( year => 2007, month => 6, day => 1 );
my $period_end   = DateTime->new( year => 2007, month => 7, day => 1 );

# подготовка и исполнение sql запроса на выборку данных
my $sth = $dbh->prepare( q/
    SELECT `src`, `dst`, `start`, `answer`, `end`, `duration`
    FROM   `cdr`
    WHERE  `start` BETWEEN ? AND ?
/ );
$sth->execute( $period_begin, $period_end );

# извлечение данных из базы и подготовка их для шаблона
my @report_data;
while ( my $report_row = $sth->fetchrow_hashref ) {
    push @report_data, $report_row;
}

# формирование excel отчета по шаблону и данным
my $template_file = 'report.xml';
my $template = Excel::Template->new( filename => $template_file );
$template->param( report_data => \@report_data );
print $template->output;

Скрипт report.pl выдает excel отчет на стандартный поток вывода, поэтому вызывать его нужно так: « ./report.pl > report.xls ». Как видите — ничего сложного. Подобным же образом можно генерировать excel документы и для web.

P.S. Данный скрипт работоспособный, хотя и был немного упрощен, чтобы донести основную идею использования шаблонов. На самом деле условия отбора записей сложнее, период формирования отчета задается в аргументах скрипта report.pl; даты преобразуются во внутренний формат excel, а не вставлются текстовой строкой; решены вопросы c кодировками. Но опытному perl программисту не составит труда адаптировать этот скрипт под свои нужды.

среда, 4 июля 2007 г.

Установка perl модулей

CPAN - это средоточие интеллектуальной мощи десятков известных и (и сотен не очень известных) perl-хакеров. Это сетевой архив тысяч perl модулей, охватывающий абсолютно все мыслимые области применения программирования. Определенно, perl сегодня не занимал бы того место, которое он занимает сейчас, если бы не было CPAN, отметившего в 2005 году своё десятилетие. Правилом любого perl программиста должно быть: сначала ищи на CPAN и только потом, в случае отсутствия там, уже пиши сам. Ведь работодатель вас ценит и платит за то, что вы умеете быстро собирать работающие машины (программы) из готовых запчастей (perl модули из CPAN), а не тратите недели рабочего времени на изобретение заново колес и шестеренок (библиотеки классов и функций). Perl модули распространяются в виде архивов исходного кода с расширением .tar.gz. В одном архиве исходного кода может быть несколько perl модулей. Основной веб-интерфейс для работы с CPAN — http://search.cpan.org. На этом сайте можно найти интересующий perl модуль по структурированному каталогу или по имени. Для каждого модуля можно прочитать встроенную документацию и исходный код. Как правило, все perl модули очень хорошо документированы. Естественно, можно скачать архив исходного кода. В каждом архиве исходного кода прилагается инструкция по установке, обычно она включает распаковку архива и выполнение команд:
perl Makefile.PL
make
make test
make install
Такой метод установки прекрасно работает, но им неудобно пользоваться. Почему? Из-за зависимостей модулей. Например, для установки часто используемой библиотеки модулей LWP (libwebperl — библиотека для работы с web из perl) требуются уже установленные perl модули: URI, Compress::Zlib, HTML::Parser. В свою очередь, для установки модуля Compress::Zlib требуются уже установленные модули: IO::Uncompress::Gunzip, IO::Compress::Gzip, Compress::Raw::Zlib, IO::Uncompress::Base, IO::Compress::Gzip::Constants, IO::Compress::Base и IO::Compress::Base::Common. И так далее... дерево зависимостей может быть очень большим. Скачивать и устанавливать все модули в ручную — просто потеря времени. Для автоматизации процесса разрешения зависимостей существует специальный perl модуль CPAN. В его состав входит утилита cpan, предоставляющая консоль доступа к архиву. Ею мы и будем пользоваться. При первом запуске утилиты будет задано несколько вопросов по параметрам конфигурации. Ответы по умолчанию выбраны достаточно разумно, поэтому я не вижу смысла отказываться от автоматического конфигурирования:
root@slack11:~# cpan
/usr/lib/perl5/5.8.8/CPAN/Config.pm initialized.
...
Are you ready for manual configuration? [yes] no
...
cpan shell -- CPAN exploration and modules installation (v1.7602)
cpan>
Если для доступа в интернет используется http proxy сервер, то необходимо задать параметры ftp_proxy и http_proxy. Если proxy сервер требует авторизацию, то url задается по схеме "http://login:password@adrr:port/":
cpan> o conf ftp_proxy "http://adrr:port/"
    ftp_proxy          http://adrr:port/
cpan> o conf http_proxy "http://adrr:port/"
    http_proxy         http://adrr:port/
cpan> o conf commit
Чтобы проверить связь cpan с внешним миром, можно загрузить информацию о текущем состоянии базы данных модулей:
cpan> reload index
Теперь модуль CPAN сконфигурирован и готов к работе. Например, можно установить уже упоминавшуюся библиотеку LWP со всеми зависимостями с помощью команды:
cpan> install LWP
Остается только смотреть на мелькающие надписи, чувствуя себя в матрице. Однако полностью расслабится не удастся, изредка придется отвечать на возникающие на экране на вопросы. Вот собственно и всё, теперь установить любой perl модуль — дело нескольких минут. В завершение хочется отметить, что алгоритм разрешения зависимостей модулей постоянно совершенствуется, changelog впечатляет. Поэтому можно порекомендовать обновить саму утилиту cpan и установить дополнительные модули, облегчающие её работу. Утилита cpan может обновить сама себя, для этого следует выполнить команду:
cpan> install Bundle::CPAN
После обновления утилиты cpan, её надо перезапустить, чтобы изменения вступили в силу. Скорее всего придется заново пройти этап конфигурирования, в автоматическом режиме, конечно :-). Вы сразу заметите, что в консоле cpan появилась возможность пролистать историю ранее введенных команд.