Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
2003 г

postfix 2, cyrus-sasl 2, kaspersky antivirus, spamassassin, courier-imap, tls, mysql how-to (FreeBSD4 STABLE)

Дмитрий Суходоев, http://raven.elk.ru

  1. прелюдия.

    всё, что описано в данном how-to вы используете на свой страх и риск. я, как автор за ваши действия и любые потери, связанные с ними ответственности не несу. кое-что для этого how-to я взял из how-to mysql+cyrus-sasl+courier-imap+postfix+openssl Вячеслава Калошина, пусть не обижается - я не присваиваю авторство, а information must be free.

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

    кроме того, всё, что здесь описано - описано исключительно для операционной системы FreeBSD 4-STABLE и для других unix-like ОС это очень и очень вряд ли подойдёт. особенно для пингинуксов. ну не символично ли: птица которая не умеет летать.


  2. введение.

    для чего всё это нужно. наша задача заключается в том, чтобы создать близкую к идеальной почтовую систему, которая могла бы делать с почтой абсолютно всё и без головной боли. необходимое для этого ПО уже существует достаточно давно и нужно лишь свести его в одно целое, чем мы и займёмся. если вы уже знакомы с данным набором ПО, то можете пропустить остаток введения и читать дальше. но можете и прочитать, всё таки я старался ;-)

    • postfix 2

      вообще, до некоторого времени стандартным решением был sendmail. но когда я начал заниматься *nix системами, то postfix существовал уже как достаточно стабильный проект (только появилась версия 1) с нормальным конфигурированием, в котором не нужно было изучать жестокий язык sendmail а также непонятно зачем нужный язык макросов m4. собственно postfix и был выбран за внятное конфигурирование, до которого sendmail'у как пешком до луны.

    • cyrus-sasl 2

      собственно, другого SASL (модуля авторизации для SMTP) я не нашёл. да и этот очень неплохо выполняет свои функции.

    • kaspersky antivirus

      вот это уже всего лишь моё личное предпочтение. лаборатория Касперского™ прекрасно разбирает вирусы, регулярно пополняет антивирусную базу, да и что уж скромничать: антивирус у них прекрасный. но всё это справедливо для их windows-продуктов, а под *nix они программировать совершенно не умеют. именно поэтому я не стал использовать в своей конструкции их kavdaemon и kav/postfix, ибо их надо запускать с привилегиями root, а этого мне совсем не хочется делать :-)

    • spamassassin

      великолепный инструмент для борьбы со спамом. содержит большое количество критериев отбора спама и письма спамеров, которые не знают о существовании spamassassin, очень хорошо ловит.

    • courier-imap

      простой и понятный pop3/imap сервер, работает с maildir, что нам и нужно. умеет брать данные о пользователях из mysql/postgresql чем и отличен. больше ничего хорошего, как, собственно, и плохого про него сказать не могу :)

    • mysql

      записная книжка с sql интерфейсом. может выдать данные из базы по запросу, а может положить данные в базу по запросу. больше ничего не умеет, но от неё ничего и не требуется.


  3. настройка mysql

    в этом пункте я намеренно пропускаю описание установки и конфигурирования mysql как sql сервера и расскажу только то, что нужно непосредственно для работы нашей системы. делаю это я для того, чтобы на самом начале отсеять людей ничего не понимающих из того, что мы собираемся делать и кроме того, я уже давно потерял интерес к mysql как самостоятельному sql серверу.

    • итак, создаём базу данных для наших программ:

      create database mail;
      use mail;
           
    • создаём таблицы с необходимыми индексами. первая таблица transport - описания транспортов для наших виртуальных доменов. сразу добавляем туда наш единственный домен - raven.elk.ru с транспортом virtual.

      create table transport(
       domain varchar(255) not null default '',
       transport varchar(255) not null default '',
       comment text,
       primary key(domain)
      );
      
      insert into transport(domain, transport)
       values('raven.elk.ru','virtual:');
           
    • следующая таблица - алиасы адресов. смысл её в том, что если postfix увидит письмо на адрес указанный в поле alias, то это письмо будет переправлено на адрес в соответствующем поле rcpt. адреса в полях могут принадлежать одинаковым доменам, разным доменам, а так же там могут быть адреса, которые не принадлежат нашим доменам ;) просто если, вдруг, письма с такими адресами получателя будут проходить через наш MTA (например от наших пользователей), то postfix изменит их адреса получателя и письма уйдут туда, куда мы их отправим.

      create table aliases(
       alias varchar(255) not null default '',
       rcpt varchar(255) not null default '',
       comment text,
       primary key(alias)
      );
      
      insert into aliases(alias, rcpt)
       values('root@raven.elk.ru', 'iam@raven.elk.ru');
      
      insert into aliases(alias, rcpt)
       values('abuse@raven.elk.ru', 'iam@raven.elk.ru');
      
      insert into aliases(alias, rcpt)
       values('mailer-daemon@raven.elk.ru', 'iam@raven.elk.ru');
      
      insert into aliases(alias, rcpt)
       values('postmaster@raven.elk.ru', 'iam@raven.elk.ru');
      
      insert into aliases(alias, rcpt)
       values('hostmaster@raven.elk.ru', 'iam@raven.elk.ru');
      
      insert into aliases(alias, rcpt)
       values('iam@raven.elk.ru', 'me@raven.elk.ru');
           
    • далее идёт таблица - список наших логинов. поля login, password и maildir очевидны, можете посмотреть на примере в insert. единственное, хотелось бы подчеркнуть, что значения поля maildir обязательно должны заканчиваться знаком '/' (slash) иначе virtual (транспорт) почту будет валить в обычный unix mailbox с соответствующим именем, а нам нужен именно maildir. если бы не тупой mysql в качестве sql сервера, то можно было бы установить rule и trigger, которые бы самостоятельно заполняли поля исходя из логина, но в mysql такого без порядочного геморроя не сделать.

      поля expired, antivirus и antispam соответственно обозначают expired ли логин, нужно ли проверять его антивирусом и антиспамом. подобные услуги для пользователей стоит делать платными, так как всё таки они откушивают очень много ресурсов у почтового сервера по сравнением с обычной доставкой почты. а антивирус вообще стоит денег, хоть тут мы его и будем использовать бесплатно, пользуясь дыркой в системе работы с ключами ;-) что совершенно законно, между прочим.

      create table users(
       login varchar(255) not null default '',
       password varchar(255) not null default '',
       maildir varchar(255) not null default '',
       expired char default '0',
       antivirus char default '1',
       antispam char default '1',
       comment text,
       primary key(login),
       key login_expired(login, expired),
       key login_antivirus(login, antivirus),
       key login_antispam(login, antispam)
      );
      
      insert into users(login, password, maildir)
       values('me@raven.elk.ru', encrypt('password:)'), 'raven.elk.ru/me/');
      
      insert into users(login, password, maildir)
       values('test@raven.elk.ru', encrypt('password1:)'), 'raven.elk.ru/test/');
      
      insert into users(login, password, maildir)
       values('test1@raven.elk.ru', encrypt('password2:)'), 'raven.elk.ru/test1/');
           
    • казалось бы это всё, но нет. следующая таблица решает проблему 'старшего брата'. здесь мы не будем обсуждать моральную сторону этого вопроса, но ни для кого не секрет, что очень многие гендиры корпораций желают (и получают) копии всех писем сотрудникам на свой ящик. опция always_bcc в postfix решает этот вопрос, но мы же крутые админы и не хотим, чтобы начальник читал нашу личную почту, верно? да и не только нашу. всегда существуют исключения в виде симпатичных секретарш или других особей женского пола которые рады отблагодарить админа за его доброту. шутка ;-)

      примеры insert'ов демонстрируют систему работы скрипта, который обрабатывает эту таблицу. первое правило:

      поле type 'delivered-to'. этим правилом будут ловится все письма, у которых в служебной строке delivered-to встретился адрес, попавший под маску в регулярных выражениях, соответствующую полю mask (персонально для mysql не забываем экранировать знак back slash '\' им же самим, а для перловых регэкспов служебные символы). в поле forward_addr хранится адрес, на который нужно копировать письмо, если оно подошло под условия. поле what установлено в буковку 'i', что значит (i)nclude, т.е. включающее правило. таким образом в первом примере будет ловится вся почта для домена raven.elk.ru и копироваться на адрес me@raven.elk.ru.

      второе правило - это исключение из первого примера адреса test1@raven.elk.ru. т.о. в комплексе этих двух правил на адрес me@raven.elk.ru будет копироваться вся почта для домена raven.elk.ru, исключая адрес test1@raven.elk.ru.

      create table forward(
       id int(10) unsigned not null auto_increment,
       type varchar(50) not null default 'delivered-to',
       mask varchar(255) not null default '.+',
       forward_addr varchar(255) not null default 'root',
       what char not null default 'i',
       comment text,
       primary key(id),
       key what(what),
       key type_mask(type, mask)
      );
      
      insert into forward(type, mask, forward_addr, what, comment)
       values('delivered-to', '[a-z0-9\- _]+\\@raven\\.elk\\.ru', 
       'me@raven.elk.ru', 'i', 'forwarding all mail for raven.elk.ru');
      
      insert into forward(type, mask, forward_addr, what, comment)
       values('delivered-to', 'test1\\@raven\\.elk\\.ru', 
       'me@raven.elk.ru', 'e', 'exclude forward test1 mail');
           
    • теперь осталось создать пользователей в mysql и выдать им соответствующие права на доступ к нашим таблицам. пользователь mailer - это наши демоны, в числе которых будет postfix, courier-imap и cyrus-sasl2 в лице pam-mysql :-) а пользователь mail_admin - это эникейщик в нашей конторе, которого можно допустить до базы через phpMyAdmin и заставить его самого делать почтовые эккаунты юзерам, а самим расслабляться и пить пиво ;)

      grant select on mail.* to mailer@localhost
       identified by 'mailer_password';
      
      grant select, insert, update on mail.* to mail_admin@localhost
       identified by 'mail_admin_password';
           

  4. настройка MTA/MDA

    в этом разделе мы начнём с конца и поставим сначала то, что нужно основному "виновнику торжества" - postfix'у.


    cyrus-sasl2

    для начала поставим cyrus-sasl2. в зависимости от свежести вашего дерева портов может быть два варианта. для более старого дерева портов вы можете просто сделать:

    cd /usr/ports/security/cyrus-sasl2
    make -DWITHOUT_OTP -DWITHOUT_CRAM -DWITHOUT_DIGEST -DWITHOUT_NTLM
       

    перед началом сборки должно вылезти красивое текстовое окошечко с кучей опций, из которых для нас важна только одна. остальные желательно убрать, оставив только:

    [X] SASLAUTHD
       

    после того, как cyrus-sasl2 собрался, то стандартно:

    make install clean
       

    ежели красивого окошечка не выскакивало, то, значит, у вас свежие порты и после всех этих действий у вас все ещё не хватает нужного нам saslauthd. его можно поставить вот таким образом:

    cd /usr/ports/security/cyrus-sasl2-saslauthd
    make install clean
       

    но повторяю, что данный порт есть только в новых портах, в старых портах он включён в порт cyrus-sasl2 и не нужен. теперь поправим конфиг для активации этого самого saslauthd в postfix. редактируем /usr/local/lib/sasl2/smtpd.conf:

    pwcheck_method: saslauthd
       

    теперь надо поставить pam-mysql. это делается стандартно:

    cd /usr/ports/security/pam-mysql
    make install clean
       

    после прочтения и осмысливания /usr/local/share/doc/pam_mysql/Readme добавим в /etc/pam.conf следующие строчки:

    smtp auth    sufficient pam_mysql.so user=mailer passwd=mailer_password db=mail 
     table=users usercolumn=login passwdcolumn=password crypt=1 where=expired=0
    smtp account sufficient pam_mysql.so user=mailer passwd=mailer_password db=mail 
     table=users usercolumn=login passwdcolumn=password crypt=1 where=expired=0
       

    не забудем запустить saslauthd:

    /usr/local/etc/rc.d/saslauthd.sh start
    ps ax|grep sasl
      363  ??  IWs    0:00,00 /usr/local/sbin/saslauthd -a pam
      367  ??  IW     0:00,00 /usr/local/sbin/saslauthd -a pam
      368  ??  IW     0:00,00 /usr/local/sbin/saslauthd -a pam
      369  ??  IW     0:00,00 /usr/local/sbin/saslauthd -a pam
      370  ??  IW     0:00,00 /usr/local/sbin/saslauthd -a pam
       

    если результат примерно такой, то значит всё прошло нормально, cyrus-sasl2 поставлен и теперь можно перейти к настройке postfix.


    postfix2

    как обычно:

    /usr/ports/mail/postfix
    make install clean
       

    должна вылезти красивая и совсем не юниксоидная ;) менюшка, в которой нам надо выбрать следующие опции:

    [X] SASL2
    [X] TLS
    [X] MySQL
       

    если какой-то из опций у вас не обнаружилось, поздравляю, у вас ну очень старые порты и надо обновлять. как это делать - не в этом how-to да и вообще ни в каком, читайте handbook - там всё написано. после установки порт должен сказать, что делать дальше это мы сразу и сделаем. в /etc/rc.conf исправим:

    sendmail_enable="NONE"
       

    в /etc/periodic.conf:

    daily_clean_hoststat_enable="NO"
    daily_status_mail_rejects_enable="NO"
    daily_status_include_submit_mailq="NO"
    daily_submit_queuerun="NO"
       

    сделаем симлинк для автоматического запуска postfix во время загрузки системы:

    cd /usr/local/etc/rc.d
    ln -s /usr/local/sbin/postfix postfix.sh
       

    откроем /usr/local/etc/postfix/main.cf в каком-нибудь текстовом редакторе, найдём в его теле и исправим следующие параметры:

    default_privs = nobody
    mynetworks = 127.0.0.0/8
    alias_maps = hash:/etc/mail/aliases
    alias_database = hash:/etc/mail/aliases
    mail_spool_directory = /var/mail
    smtpd_banner = $myhostname mail sterver
       

    не торопимся сохранять и закрывать /usr/local/etc/postfix/main.cf, а допишем туда:

    # с каким кодом отшивать письма от open relays:
    maps_rbl_reject_code = 554
    
    # принимать письма от:
    #  авторизованных клиентов
    #  от сетей, указанных в параметре mynetworks
    # отшивать письма от:
    #  не для наших доменов и пользователей
    #  для хостов, который есть в списках open relays
    #  (подробности на www.ordb.org)
    smtpd_recipient_restrictions =
     permit_sasl_authenticated,
     permit_mynetworks,
     reject_unauth_destination,
     reject_rbl_client	list.dsbl.org,
     reject_rbl_client	relays.ordb.org,
     reject_rbl_client	dynablock.wirehub.net,
     reject_rbl_client	blackholes.wirehub.net,
     reject_rbl_client	dnsbl.njabl.org
    
    # списки транспортов:
    transport_maps = mysql:/usr/local/etc/postfix/sql/transport.cf
    
    # куда складывать почту транспорту virtual:
    virtual_mailbox_base = /var/mail/virtual
    
    # списки почтовых ящиков:
    virtual_mailbox_maps = mysql:/usr/local/etc/postfix/sql/users.cf
    
    # списки алиасов:
    virtual_alias_maps = mysql:/usr/local/etc/postfix/sql/aliases.cf
    
    # списки uid и gid пользователей:
    virtual_uid_maps = mysql:/usr/local/etc/postfix/sql/uids.cf
    virtual_gid_maps = mysql:/usr/local/etc/postfix/sql/gids.cf
    
    # списки наших доменов, для которых мы принимаем почту
    relay_domains = $transport_maps
    
    # списки наших пользователей:
    local_recipient_maps = $virtual_mailbox_maps $virtual_maps $transport_maps
    
    # включаем плагин sasl2 для smtpd авторизации
    smtpd_sasl_auth_enable = yes
    smtp_sasl_security_options = noanonymous
    broken_sasl_auth_clients = yes
    
    # использовать transport layer security для отправки почты
    # (пока все оставляем закомментаренным, ибо ключей у нас ещё нет)
    #smtp_use_tls = yes
    
    # наши ключи. генерируются с помощью courier-imap (далее)
    #smtp_tls_key_file = /usr/local/share/courier-imap/pop3d.pem
    #smtp_tls_cert_file = $smtp_tls_key_file
    #smtp_tls_CAfile = $smtp_tls_key_file
    #smtp_tls_note_starttls_offer = yes
    
    # включать возможность авторизации только в режиме tls
    #smtpd_tls_auth_only = yes
    
    # использовать tls для приёма почты
    #smtpd_use_tls = yes
    #smtpd_tls_loglevel = 1
    #smtpd_tls_received_header = yes
    #smtpd_tls_session_cache_timeout = 3600s
    #tls_random_source = dev:/dev/urandom
    
    # наши ключи. генерируются с помощью courier-imap (далее)
    #smtpd_tls_key_file = /usr/local/share/courier-imap/pop3d.pem
    #smtpd_tls_cert_file = $smtpd_tls_key_file
    #smtpd_tls_CAfile = $smtpd_tls_key_file
       

    сохраняем /usr/local/etc/postfix/main.cf и напишем maps файлы для mysql:

    /usr/local/etc/postfix/sql/transport.cf:
    user = mailer
    password = mailer_password
    dbname = mail
    table = transport
    select_field = transport
    where_field = domain
    hosts = localhost
    
    /usr/local/etc/postfix/sql/users.cf
    user = mailer
    password = mailer_password
    dbname = mail
    table = users
    select_field = maildir
    where_field = login
    additional_conditions = and expired = '0'
    hosts = localhost
    
    /usr/local/etc/postfix/sql/aliases.cf:
    user = mailer
    password = mailer_password
    dbname = mail
    table = aliases
    select_field = rcpt
    where_field = alias
    hosts = localhost
    
    /usr/local/etc/postfix/sql/gids.cf:
    user = mailer
    password = mailer_password
    dbname = mail
    table = users
    select_field = 6
    where_field = login
    additional_conditions = and expired = '0'
    hosts = localhost
    
    /usr/local/etc/postfix/sql/uids.cf:
    user = mailer
    password = mailer_password
    dbname = mail
    table = users
    select_field = 1009
    where_field = login
    additional_conditions = and expired = '0'
    hosts = localhost
       

    по поводу последних двух файлов нужно заметить, что реально полей для gid и uid в таблицах нет, ибо они все одинаковые и прописаны прямо в параметре select_field. чтобы узнать значения gid и uid для вашей системы, вам нужно посмотреть в /etc/passwd и /etc/group какие uid и gid принадлежат пользователю postfix (которого добавляет порт /usr/ports/mail/postfix) и группе mail. и прописать соответствующие значения в последних двух sql файлах.

    если вы всё сделали правильно, то ваш MTA и MDA успешно настроен. теперь нужно создать каталог virtual mailbox base и выставить ему атрибутов:

    mkdir -pv /var/mail/virtual
    chown postfix:mail /var/mail/virtual
    chmod 770 /var/mail/virtual
       

    теперь можно запускать postfix. запускаем для начала 'postfix check' и смотрим, что он скажет на свою конфигурацию. если всё нормально, то запускаем: 'postfix start'. если postfix на что-то ругнулся, то надо это что-то исправить, к тому же postfix он не настолько злобный и на всякую ерунду не ругается.

    ну что ж, настала пора проверить SMTP часть нашего MTA:

    telnet localhost 25
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    220 raven.elk.ru mail sterver
    mail from: user@aol.com
    250 Ok
    rcpt to: me@raven.elk.ru
    250 Ok
    data
    354 End data with <CR><LF>.<CR><LF>
    test message
    .
    250 Ok: queued as AB11E334F2
    quit
    221 Bye
    Connection closed by foreign host.
       

    если у вас в консоли всё примерно так же, как и выше, то SMTP часть у вас работает нормально.

    теперь проверим возможность авторизации:

    telnet localhost 25
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    220 raven.elk.ru mail sterver
    ehlo aol.com
    250-raven.elk.ru
    250-PIPELINING
    250-SIZE 10240000
    250-VRFY
    250-ETRN
    250-AUTH LOGIN PLAIN
    250-AUTH=LOGIN PLAIN
    250-XVERP
    250 8BITMIME
    AUTH PLAIN bWVAcmF2ZW4uZWxrLnJ1AG1lQHJhdmVuLmVsay5ydQBwYXNzd29yZDop
    235 Authentication successful
       

    строка 'bWVAcmF2ZW4uZWxrLnJ1AG1lQHJhdmVuLmVsay5ydQBwYXNzd29yZDop' справедлива для логина 'me@raven.elk.ru' и пароля 'password:)'. генерируется эта строчка следующим образом:

    perl -MMIME::Base64 -e \
     'print encode_base64("логин\0логин\0пароль");'
       

    если диалог с почтовым сервером прошёл как показано выше, то значит авторизация работает. если же нет, то, читайте /var/log/maillog. вероятно, вы что-то не так сделали и очень вероятно, что чтение данного лога поможет выяснить что же конкретно неправильно.


  5. настройка POP3 сервера

    роль POP3 сервера в нашей системе играет courier-imap. хоть он и называется -imap, но умеет работать на двух разных протоколах: IMAP и POP3. первый лично мне совсем-совсем не нужен, поэтому я использую только второй. вот его-то мы сейчас и настроим. для начала поставим этот самый courier-imap:

    cd /usr/ports/mail/courier-imap
    make -DWITH_MYSQL install clean
    cd /usr/local/etc/courier-imap
    cp authdaemonrc.dist authdaemonrc
    cp authmysqlrc.dist authmysqlrc
    cp authdaemonrc.dist authdaemonrc
    cp authmysqlrc.dist authmysqlrc
    cp pop3d.dist pop3d
    cp pop3d-ssl.dist pop3d-ssl
    cp pop3d.cnf.dist pop3d.cnf
    cd /usr/local/etc/rc.d
    rm courier-imap-imapd.sh.sample
    rm courier-imap-pop3d.sh.sample
    ln -s /usr/local/libexec/courier-imap/pop3d.rc pop3d.sh
    ln -s /usr/local/libexec/courier-imap/pop3d-ssl.rc pop3d-ssl.sh
       

    редактируем /usr/local/etc/courier-imap/authdaemonrc:

    authmodulelistorig="authmysql"
    daemons=5
    version=""
    authdaemonvar=/usr/local/var/authdaemon
       

    редактируем /usr/local/etc/courier-imap/authmysqlrc:

    MYSQL_SERVER		localhost
    MYSQL_USERNAME		mailer
    MYSQL_PASSWORD		mailer_password
    MYSQL_SOCKET		/var/tmp/mysql.sock
    MYSQL_PORT		3306
    MYSQL_OPT		0
    MYSQL_DATABASE		mail
    MYSQL_USER_TABLE	users
    MYSQL_CRYPT_PWFIELD	password
    MYSQL_UID_FIELD		1009
    MYSQL_GID_FIELD		6
    MYSQL_LOGIN_FIELD	login
    MYSQL_HOME_FIELD	'/var/mail/virtual/'
    MYSQL_MAILDIR_FIELD	maildir
    MYSQL_WHERE_CLAUSE	expired = '0'
       

    редактируем /usr/local/etc/courier-imap/pop3d:

    prefix=/usr/local
    exec_prefix=/usr/local
    sbindir="/usr/local/sbin"
    PIDFILE=/var/run/pop3d.pid
    MAXDAEMONS=11
    MAXPERIP=3
    AUTHMODULES="authdaemon"
    AUTHMODULES_ORIG="authdaemon"
    POP3AUTH="LOGIN PLAIN"
    POP3AUTH_ORIG="LOGIN PLAIN"
    POP3AUTH_TLS="LOGIN PLAIN"
    POP3AUTH_TLS_ORIG="LOGIN PLAIN"
    PORT=110
    ADDRESS=0
    TCPDOPTS="-nodnslookup -noidentlookup"
    POP3DSTART=YES
       

    редактируем /usr/local/etc/courier-imap/pop3d-ssl:

    prefix=/usr/local
    exec_prefix=/usr/local
    SSLPORT=995
    SSLADDRESS=0
    SSLPIDFILE=/var/run/pop3d-ssl.pid
    POP3DSSLSTART=YES
    POP3DSTARTTLS=YES
    POP3_TLS_REQUIRED=0
    COURIERTLS=/usr/local/bin/couriertls
    TLS_PROTOCOL=SSL3
    TLS_STARTTLS_PROTOCOL=TLS1
    TLS_CERTFILE=/usr/local/share/courier-imap/pop3d.pem
    TLS_VERIFYPEER=NONE
       

    теперь сгенерируем сертификат для нашего почтового сервера. для этого сначала нужно отредактировать /usr/local/etc/courier-imap/pop3d.cnf:

    RANDFILE = /usr/local/share/courier-imap/pop3d.rand
    
    [ req ]
    default_bits = 4096
    encrypt_key = yes
    distinguished_name = req_dn
    x509_extensions = cert_type
    prompt = no
    
    [ req_dn ]
    C=ru
    ST=ch
    L=chicaginsk
    O=raVen's mail sterver
    OU=raVen's ssl key
    CN=mail.raven.elk.ru
    emailAddress=postmaster@raven.elk.ru
    
    [ cert_type ]
    nsCertType = server
       

    запустим генерилку сертификатов:

    rm /usr/local/share/courier-imap/pop3d.pem
    /usr/local/share/courier-imap/mkpop3dcert
       

    оно будет очень долго возиться с генерацией случайных значений, вы в это время можете поделать чего-нибудь своё, либо пойти попить кофе. после готовности сертификата можно запускать courier-imap:

    /usr/local/etc/rc.d/pop3d.sh start
    /usr/local/etc/rc.d/pop3d-ssl.sh start
       

    ну и как обычно, проверим его:

    telnet localhost 110
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    +OK Hello there.
    user me@raven.elk.ru
    +OK Password required.
    pass password:)
    +OK logged in.
    list
    +OK POP3 clients that break here, they violate STD53.
    1 623
    .
    quit
    +OK Bye-bye.
    Connection closed by foreign host
       

    так как наш сертификат готов теперь можно раскомментировать tls часть main.cf у postfix, и перезапустить его: 'postfix reload'. теперь на ehlo он кроме всего прочего будет предлагать ещё и опцию STARTTLS и доставлять письма на удалённые smtp тоже будет по TLS, если удалённый сервер на ehlo среди прочего отвечает STARTTLS.


  6. настройка фильтров (антивирус, антиспам и форвардер)

    я сразу хотел бы заметить, что все фильтры в данном how-to представляют собой perl скрипты со всеми вытекающими последствиями. отсюда следует, что вам стоит сопоставить конфигурацию своего почтового сервера с нагрузкой на него, что бы не получилось так, что в результате работы фильтров пропускная способность сервера оказалась меньше средней почтовой нагрузки. например, spamassasin даже на очень хорошей машине (в моём случае это p3-866/256ram) обычное письмо обрабатывает более 10 секунд. а если письмо большое, то и того больше.

    но в принципе ничего страшного в том, что вы сейчас настроите фильтры нет, ибо, как можно было убедиться при создании таблиц в mysql, всем пользователям фильтры можно отключить и письмо будет летать мимо них, пусть загружая сервер собой чуть больше, но нагрузка эта незначительная. если вы все ещё со мной, тогда вперёд!

    kaspersky antivirus

    поставим его, родного. живёт package для BSD систем где-то в районе ftp://ftp.avp.ru/patches/. качнём и поставим его:

    cd /var/tmp
    wget -c ftp://ftp.avp.ru/patches/KAVUnix4.0.3.0_UrgentUpdate1/FreeBSD
     /4.x/kav-WorkStationSuit-4.0.3.1-FreeBSD-4.x.tgz
    pkg_add kav-WorkStationSuit-4.0.3.1-FreeBSD-4.x.tgz
       

    нефиг ему запускаться под рутом:

    rm -f /usr/local/etc/rc.d/kavd.sh
       

    теперь, если вы хотите использовать kavscanner совершенно законно и нахаляву, то вам необходимо скачать вот этот файлик. внутри архива находится старая версия kavscanner, которая глючит при работе со своими же ключами и при комбинации двух определённых ключей всегда считает себя зарегистрированной. как вы правильно догадались, эти два ключа лежат в том же архиве ;-) вам нужно заменить kavscanner из дистрибутива бинарником из архива и положить два ключа в /etc/AVP.

    теперь нам надо подкорректировать конфиги Касперского. идём в /etc/AVP и правим. описание конфигов есть на том же ftp://ftp.avp.ru где-то в районе документации. там такой здоровый pdf метров на 10, в котором подробное описание всего пакета. среди него есть и описания конфигов. я просто привожу здесь свои варианты конфигов. они у меня работают на нескольких серверах.
    /etc/AVP/AvpUnix.ini:

    [AVP32]
    DefaultProfile=/etc/AVP/defUnix.prf
    
    [Configuration]
    KeysPath=/etc/AVP
    SetFile=avp.set
    BasePath=/var/AVP/Bases
    SearchInSubDir=No
    UpdatePath=ftp://ftp.kasperskylab.ru/updates
       

    /etc/AVP/defUnix.prf

    [Object]
    Names=*/var/tmp;*/tmp
    Memory=No
    Sectors=No
    ScanAllSectors=No
    Files=Yes
    FileMask=2
    UserMask=*.tar.gz
    ExcludeFiles=0
    ExcludeMask=*.txt *.cmd
    ExcludeDir=
    Packed=Yes
    Archives=Yes
    SelfExtArchives=Yes
    MailBases=Yes
    MailPlain=Yes
    Embedded=Yes
    InfectedAction=0
    BackupInfected=No
    IfDisinfImpossible=0
    DeleteInfectedArch=No
    Warnings=Yes
    CodeAnalyser=Yes
    RedundantScan=No
    SubDirectories=Yes
    CrossFs=Yes
    
    [Options]
    ScanRemovable=No
    ScanSubDirAtEnd=No
    ParallelScan=No
    LimitForProcess=16
    EndlesslyScan=No
    ScanDelay=-1
    Symlinks=0
    
    [Report]
    Report=Yes
    UseSysLog=No
    ReportFileName=/var/log/kavscan.log
    Append=Yes
    ReportFileLimit=Yes
    ReportFileSize=1024
    RepCreateFlag=644
    ExtReport=Yes
    WriteTime=Yes
    WriteExtInfo=No
    UseCR=No
    RepForEachDisk=Yes
    LongStrings=Yes
    UserReport=No
    UserReportName=~/.AVP/userreport.log
    ShowOK=No
    ShowPack=Yes
    ShowPassworded=Yes
    ShowSuspision=Yes
    ShowWarning=Yes
    ShowCorrupted=Yes
    ShowUnknown=Yes
    
    [ActionWithInfected]
    InfectedCopy=No
    InfectedFolder=~/.AVP/infected
    CopyWithPath=Yes
    ChangeExt=None
    NewExtension=Virs
    ChownTo=None
    ChModTo=No
    
    [ActionWithSuspicion]
    SuspiciousCopy=No
    SuspiciousFolder=~/.AVP/suspicious
    CopyWithPath=Yes
    ChangeExt=None
    NewExtension=Susp
    ChownTo=None
    ChModTo=No
    
    [ActionWithCorrupted]
    CorruptedCopy=No
    CorruptedFolder=~/.AVP/corrupted
    CopyWithPath=Yes
    ChangeExt=None
    NewExtension=Corr
    ChownTo=None
    ChModTo=No
    
    [TempFiles]
    UseMemoryFiles=Yes
    LimitForMemFiles=6000
    MemFilesMaxSize=20000
    TempPath=/var/tmp
    
    [Priority]
    Father=0
    Child=0
    
    [Customize]
    Sound=No
    UpdateCheck=No
    UpdateInterval=90
    OtherMessages=Yes
    RedundantMessage=No
    DeleteAllMessage=Yes
    ExitOnBadBases=Yes
    UseExtendedExitCode=Yes
       

    так же в пакете kav-scanner идёт утилита и скрипт для обновления антивирусных баз. утилита вроде бы нормальная, хоть и требует wget :) а вот вот скрипт дико кривой. я не помню, что я там уже правил, а правил, видимо всё таки много, так как отличий от стандартного нашлось целая куча. в общем вот он этот скрипт /etc/periodic/daily/900.kavupdater:

    #!/bin/sh
    
    KAV_PATH=/usr/local/share/AVP
    PATH=$PATH:/usr/local/bin
    
    if [ ! -x /usr/local/bin/wget ]; then
     echo "$0: wget must be installed for the updater to run" >&2
     exit 1
    fi
    
    DESC="kaspersky anti-virus updater"
    
    if [ -r ~.AVP/AvpUnix.ini ]; then
     INIFILE=~.AVP/AvpUnix.ini
     else if [ -r /etc/AVP/AvpUnix.ini ]; then
      INIFILE=/etc/AVP/AvpUnix.ini
     fi
    fi
    
    if [ -r $INIFILE ]; then
     eval `egrep '^[A-Za-z]*=' $INIFILE | perl -pe 's/\r//g'`
    fi
    
    if [ -n "$UpdatePath" ]; then
     DPARMS="$UpdatePath"
    else
     if [ -n $1 ]; then
      echo "warning! add updatepath in your config file AvpUnix.ini"
      exit 1
     fi
     DPARMS=$1
    fi
    
    echo
    echo
    echo run kaspersky antivirus updating:
    echo checking parameters "$DPARMS"
    
    if [ $? -eq 0 ]; then
     $KAV_PATH/kavupdater -uik="$DPARMS" -o -y -kb
     exitCode=$?
     case $exitCode in
      8)
       echo 8 - new antiviral bases not found.
      ;;
      6)
       echo 6 - found corrupted file and process stoped on it.
      ;;
      4)
       echo 4 - found corrupted file.
      ;;
      2)
       echo 2 - process stoped on corrupted file.
      ;;
      0)
       echo 0 - antiviral bases correctly loaded.
      ;;
      *)
       echo $exitCode - i dont know this exit code!
     esac
    else
     echo "$0: network connection error." >&2
     exit 1
    fi
    
    exit 0
       

    запустите обновлялку /etc/periodic/daily/900.kavupdater. оно должно скачать и установить все базы для kav. после этого запуск kavscanner должен запустится проверить /tmp и ни на что не ругаться.


    spamassassin

    как обычно:

    cd /usr/ports/lang/perl5
    make install clean
    use.perl port
    cd /usr/ports/mail/p5-Mail-SpamAssassin
    make install clean
       

    потянет за собой кучу байды, но она, видимо, нужна, так что потерпите уж. perl 5.6.1 тоже нужен для фильтровых скриптов. отредактируем конфиг spamassassin. /usr/local/etc/mail/spamassassin/local.cf:

    # подробный отчёт
    clear_report_template
    report тут, похоже, привалило спама, но я его узнал и отловил. письмо, которое пришло
    report находится в приложении и его можно поглядеть, вдруг я облажался и на самом деле
    report это не спам.
    report
    report вот что там внутри: _PREVIEW_
    report
    report детали анализа текста письма: (набрано _HITS_ очков, _REQD_ необходимо)
    report _SUMMARY_
    
    # краткий отчёт
    clear_terse_report_template
    terse_report --- результаты борьбы со спамом
    terse_report набрано _HITS_ очков, _REQD_ требуется;
    terse_report _SUMMARY_
    terse_report --- конец результатов борьбы со спамом
    
    # если нет текста
    clear_unsafe_report_template
    unsafe_report а вообще это письмо не содержит текста, так что лучше его не открывать, так как
    unsafe_report там может быть вирус или подтверждение, что Ваш адрес может получать спам ;)
    unsafe_report если Вы всё таки хотите поглядеть что там такое, то лучше сохранить это письмо
    unsafe_report как файл и поглядеть его какой-нибудь внешней безопасной программой.
    
    # переписывать поле subject
    rewrite_subject 1
    subject_tag new spam received:
    
    # эти рассылки я читаю и они умудряются определяться спамом ;)
    # поэтому эти адреса добавим в whitelist
    whitelist_from subscribe@74.ru
    whitelist_from info@suct.uu.ru
    whitelist_from suct@suct.uu.ru
    whitelist_from subscribe@udaff.com
    whitelist_from genocide@raven.elk.ru
       

    кроме этого нужно добавить пользователя в системе, с правами которого будут происходить все проверки на спам и на вирусы. пользователь должен быть вот такой, добавите сами ;-)

    filter:*:1025:1025::0:0:mail filter:/var/spool/filter:/sbin/nologin
       

    напишем и запустим скрипт для запуска и останова spamd - демона, который значительно ускоряет работу spamassassin, правда отжирает много памяти, но он того стоит. /usr/local/etc/rc.d/spammerdaemon.sh:

    #!/bin/sh
    if ! PREFIX=$(expr $0 : "\(/.*\)/etc/rc\.d/$(basename $0)\$"); then
     echo "$0: Cannot determine the PREFIX" >&2
     exit 1
    fi
    case "$1" in
    start)
     kill `ps ax | grep spamd | grep -v grep | awk '{print $1}' 
     | head -1` >/dev/null 2>/dev/null && echo -n ' spamd'
     [ -x ${PREFIX}/bin/spamd ] 
     && ${PREFIX}/bin/spamd -d -a -c -u filter && echo -n ' spamd'
    ;;
    stop)
     kill `ps ax | grep spamd | grep -v grep | awk '{print $1}' 
     | head -1` >/dev/null 2>/dev/null && echo -n ' spamd'
    ;;
    *)
     echo "Usage: `basename $0` {start|stop}" >&2
    ;;
    esac
    exit 0
       

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

    /usr/local/etc/rc.d/spammerdaemon.sh start
    ps ax | grep spam
    338  ??  Is     0:07,50 /usr/local/bin/spamd -d -a -c -u filter (perl)
       

    опять postfix

    теперь вернёмся к postfix добавлять фильтры. открываем /usr/local/etc/postfix/master.cf и дописываем туда следующие строчки. обратите внимание, что для каждого фильтра (он же транспорт) указано количество максимальных процессов - 10. вам стоит поменять это на своё значение в зависимости от количества свободной памяти на вашем сервере. в принципе если её много, то можно оставить и 10. если мало, то лучше поставить значения поменьше вплоть до 1.

    # ==========================================================================
    # service type  private unpriv  chroot  wakeup  maxproc command + args
    #               (yes)   (yes)   (yes)   (never) (100)
    # ==========================================================================
    # forwarder
    forwarder
     unix		-	n	n	-	10	pipe
     flags=RD
     user=filter
     argv=/usr/local/raven/mail/forwarder.pl "localhost:10025" "${sender}" "${recipient}"
    
    # from forwarder
    localhost:10025
     inet		n	-	n	-	-	smtpd
     -o content_filter=genocide
     -o local_recipient_maps=
     -o relay_recipient_maps=
     -o smtpd_helo_restrictions=
     -o smtpd_client_restrictions=
     -o smtpd_sender_restrictions=
     -o mynetworks=127.0.0.0/8
     -o smtpd_recipient_restrictions=permit_mynetworks,reject
     -o myhostname=localhost
    
    # antivirus
    genocide  unix	-	n	n	-	10	pipe
     flags=R
     user=filter
     argv=/usr/local/raven/mail/antikav.pl "localhost:10026" "${sender}" "${recipient}"
    
    # from antivirus
    localhost:10026
     inet		n  	-	n	-	-	smtpd
     -o content_filter=spamfilter
     -o local_recipient_maps=
     -o relay_recipient_maps=
     -o smtpd_helo_restrictions=
     -o smtpd_client_restrictions=
     -o smtpd_sender_restrictions=
     -o mynetworks=127.0.0.0/8
     -o smtpd_recipient_restrictions=permit_mynetworks,reject
     -o myhostname=localhost
    
    # spamfilter
    spamfilter
     unix 		- 	n 	n 	- 	10 	pipe
     flags=R
     user=filter
     argv=/usr/local/raven/mail/std2lmtp.pl "localhost:10027" "antispam" "
     ${sender}" "${recipient}" "/usr/local/bin/spamc"
    
    # from spamfilter to smtpd:10026
    localhost:10027
     inet		n	-	n	-	-	smtpd
     -o content_filter=
     -o local_recipient_maps=
     -o relay_recipient_maps=
     -o smtpd_helo_restrictions=
     -o smtpd_client_restrictions=
     -o smtpd_sender_restrictions=
     -o mynetworks=127.0.0.0/8
     -o smtpd_recipient_restrictions=permit_mynetworks,reject
     -o myhostname=localhost
       

    а к /usr/local/etc/postfix/main.cf добавляем вот это:

    # первый из цепочки фильтров:
    content_filter = forwarder
    
    # необходимо для корректной работы скриптов!
    forwarder_destination_recipient_limit = 1
    genocide_destination_recipient_limit = 1
    spamfilter_destination_recipient_limit = 1
       

    forwarder.pl, antikav.pl и std2lmtp.pl можно найти вот в этом архиве. в каждом скрипте вначале есть мини конфигурация, в которой необходимо как минимум прописать логин и пароль для mysql.

    forwarder.pl - помощник 'старшего брата'. копирует письмо на нужный адрес в случае необходимости. если нужного адреса нет, то просто прокидывает письмо к следующему элементу в цепочке.

    antikav.pl - антивирусный фильтр. с помощью модуля MIME::Tools разбирает письмо на файлы, которые кладёт в /tmp, напускает на эти файлы kavscanner и, парся его вывод, определяет что из этих файлов заражено. заражённые файлы вычленяет из письма, собирает письмо обратно с помощью всё того же MIME::Tools и отправляет следующему фильтру в цепочке.

    std2lmtp.pl - вообще это мелкий скрипт, который переправляет содержимое stdin в на указанный адрес по smtp протоколу. в нашем случае этот скрипт кроме простого перенаправления, на письмо ещё и напускает указанную программу (spamc), которая в свою очередь соединяется со spamd, который является самом spamassassin, проверяет письмо на спамность и в случае необходимости помечает его. ну а наш скрипт потом результат отправляет в smtpd, который последний в цепочке фильтров и дальше уже идёт раскладка по почтовым ящикам.

       

  7. todo, хотелки, благодарности и всё остальное...

    • postgresql

      как я уже упоминал в начале, mysql представляет из себя записную книжку с sql интерфейсом. он, конечно, быстр, удобен для определённых задач, но держать лишний sql сервер на машине ради почты не очень хочется. сам я сейчас работаю исключительно с postgresql и хотел сделать данную связку не на основе mysql, а на основе postgresql. хотел - сделал и даже начал писать how-to по нему, но есть одна большая проблема.

      почему-то после соединений postfix или courier-imap с postgresql сервером, в памяти от них остаются процессы postmaster в состоянии idle, которые потом закрываются и сообщают в лог о том, что пришёл неожиданный eof от клиента. причем происходит это только в случае, если клиентами выступают postfix или courier-imap. pam_pgsql и мои перловые тесты отрабатывают нормально.

      если у кого-то получилось настроить postfix и courier-imap в связке с postgresql, то, пожалуйста, расскажите мне, как вы это делали, я сделаю ещё один how-to, где вместо mysql будет postgresql со всеми его фичами и, естественно обязательно упомяну вас. очень уж хочется снести mysql со своих серверов! он хоть и простой и быстрый, но память-то всё равно жрёт ;)

    • благодарности

      на самом деле мне некого благодарить за что-либо. всего приходится добиваться самому, если даже кто-то и хочет помочь, то не может, ибо это слишком сложно, а случаи в которых мне нужна чья-либо помощь обычно дико-клинические...

      поэтому я говорю спасибо только себе, за то, что ещё не сошёл с ума от всего безумства жизни, за то, что ещё жив, по прежнему быстр и рационален, хоть и постоянно занят :-(

Новости мира IT:

Архив новостей

Последние комментарии:

Сбербанк инвестировал в сервис Uber (1)
Понедельник 11.07, 09:36
Loading

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 985 1945361
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2015 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...