Блог ИТ склеротика. Почтовая система на Postfix с виртуальными доменами

Страницы

Расширенный поиск в статьях блога

12 марта 2012 г.

Почтовая система на Postfix с виртуальными доменами

HOWTO, чтобы самому не забыть, и предоставить информацию для тех, у кого возникают проблемы.

Что будет включать в себя почтовая система:

  • Почтовый сервер Postfix + виртуальные почтовые домены и пользователи
  • PostfixAdmin для управления всем хозяйством через web
  • Amavisd-new + SpamAssassin + ClamAV для борьбы со спамом и вирусами
  • Dovecot в качестве POP3(S) и IMAP(S) сервера, а также LDA
  • Механизм квотирования (Maildir++)
  • Roundcube для веб-интерфейса к почтовым ящикам
  • Тестовая система: Ubuntu 11.04 server. Работаю под рутом, поэтому sudo опускаем.
    Доменное имя для примера: example.com

    1. Установка пакетов и создание пользователя для доступа к виртуальным почтовым ящикам

    apt-get install postfix postfix-mysql maildrop apache2 php5 php5-cli php5-mysql php5-imap \
    php5-mcrypt php5-intl amavisd-new spamassassin clamav clamav-daemon dovecot-imapd \
    dovecot-pop3d mysql-server
    # Почта будет храниться здесь в виде /home/vmail/DOMAINNAME/USERNAME
    # Удаленные через PostfixAdmin домены/ящики буду храниться в /home/vmail/DELETED
    mkdir -p /home/vmail/DELETED
    # !!! UID 111 должен быть свободен, если он занят то выбираем свободный, и везде далее не забываем его поменять !!!
    useradd -r -u 111 -g mail -d /home/vmail -s /sbin/nologin -c "Virtual mailbox" vmail
    chown -R vmail:mail /home/vmail
    chmod 770 /home/vmail

    2. Установка PostfixAdmin
    PostfixAdmin — веб-интерфейс управления виртуальными почтовыми доменами и пользователями.

    Скачиваем последнюю версию с http://sourceforge.net/projects/postfixadmin:

    cd /var/www
    wget POSTFIXADMIN_URL.tar.gz
    tar -xvzf postfixadmin-2.x.x.tar.gz
    mv postfixadmin-2.x.x postfixadmin
    chown -R www-data:www-data postfixadmin

    Создаем базу данных:

    mysql -u root -p
    CREATE DATABASE postfix;
    GRANT ALL ON postfix.* TO postfix@localhost IDENTIFIED BY 'postfixpass';
    FLUSH PRIVILEGES;

    Правим /var/www/postfixadmin/config.inc.php:

    ...
    $CONF['configured'] = true;
    ...
    $CONF['postfix_admin_url'] = 'http://example.com/postfixadmin';
    $CONF['database_user'] = 'postfix';
    $CONF['database_password'] = 'postfixpass';
    $CONF['database_name'] = 'postfix';
    ...
    $CONF['admin_email'] = 'postmaster@example.com';
    ...
    $CONF['default_aliases'] = array (
    'abuse' => 'abuse@example.com',
    'hostmaster' => 'hostmaster@example.com',
    'postmaster' => 'postmaster@example.com',
    'webmaster' => 'webmaster@example.com'
    );
    ...
    $CONF['domain_path'] = 'YES';
    $CONF['domain_in_mailbox'] = 'NO';
    ...
    $CONF['fetchmail'] = 'NO';
    ...
    $CONF['mailbox_postcreation_script']='/usr/bin/sudo -u vmail /usr/local/bin/postfixadmin-mailbox-postcreation.sh';
    $CONF['mailbox_postdeletion_script']='/usr/bin/sudo -u vmail /usr/local/bin/postfixadmin-mailbox-postdeletion.sh';
    $CONF['domain_postdeletion_script']='/usr/bin/sudo -u vmail /usr/local/bin/postfixadmin-domain-postdeletion.sh';
    ...
    // Остальные параметры можно изменить по вкусу

    Заходим на http://example.com/postfixadmin/setup.php:
    Проверяем секцию «Checking for dependencies: «, там все должно быть «ОК».
    Задаем «Setup password» и меняем $CONF['setup_password'] на полученный хеш.
    Затем вводим новый Setup password, детали суперадмина и добавляем его.
    Теперь можно зайти на http://example.com/postfixadmin, используя созданного суперадмина.

    Добавляем в /etc/sudoers:

    ...
    www-data ALL=(vmail) NOPASSWD: /usr/local/bin/postfixadmin-mailbox-postdeletion.sh
    www-data ALL=(vmail) NOPASSWD: /usr/local/bin/postfixadmin-domain-postdeletion.sh
    www-data ALL=(vmail) NOPASSWD: /usr/local/bin/postfixadmin-mailbox-postcreation.sh
    ...

    Копируем скрипты, которые физически создают/удаляют домены/почтовые ящики после соответственных действий в PostfixAdmin:

    cp /var/www/postfixadmin/ADDITIONS/postfixadmin-domain-postdeletion.sh /usr/local/bin
    cp /var/www/postfixadmin/ADDITIONS/postfixadmin-mailbox-postcreation.sh /usr/local/bin
    cp /var/www/postfixadmin/ADDITIONS/postfixadmin-mailbox-postdeletion.sh /usr/local/bin

    Правим в этих скриптах параметры basedir и trashbase(где есть):

    basedir=/home/vmail
    ...
    trashbase=/home/vmail/DELETED

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

    2. Настройка Postfix

    Небольшое отступление. Я сознательно отказался от родного в postfix VDA и выбрал Dovecot LDA, поскольку для поддержки квот нужныпатч и пересборка deb-пакета. С патчем квоты тоже работают хорошо, но обновление Postfix становится более затруднительным.

    Правим /etc/postfix/main.cf:

    ...
    myhostname = mail.example.com
    myorigin = /etc/mailname
    mydestination = $myhostname, localhost.example.com, localhost
    ...
    # Таблица просмотра виртуальных доменов
    virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
    # Таблицы просмотра почтовых псевдонимов для виртуальных почтовых доменов/ящиков
    virtual_alias_maps =
       proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf,
       proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf,
       proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
    # Таблицы просмотра каталогов для хранения почты
    virtual_mailbox_maps =
       proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf,
       proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
    # !!! GID для группы mail, если он отличается, то здесь и далее меняем !!!
    virtual_gid_maps = static:8
    virtual_mailbox_base = /home/vmail
    virtual_minimum_uid = 111
    dovecot_destination_recipient_limit = 1
    # Транспорт для виртуальных доменов в virtual_mailbox_domains - Dovecot LDA
    virtual_transport = dovecot
    virtual_uid_maps = static:111
    broken_sasl_auth_clients = yes
    # Небольшие ограничения для отсылки, можно добавить и DNSBL, и т.д., кому как хочется
    smtpd_recipient_restrictions =
        permit_mynetworks,
        reject_non_fqdn_hostname,
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unauth_destination,
        reject_unauth_pipelining,
        reject_invalid_hostname
    # Добавляем проверку на вирусы и спам через amavisd-new
    content_filter = smtp-amavis:[127.0.0.1]:10024
    receive_override_options=no_address_mappings
    message_size_limit = 10485760
    strict_rfc821_envelopes = yes
    disable_vrfy_command = yes
    smtpd_helo_required = yes

    Создаем файлы для таблиц просмотра MySQL, тем самым, связывая Postfix и базу данных для PostfixAdmin.

    mkdir /etc/postfix/sql

    /etc/postfix/sql/mysql_virtual_domains_maps.cf:

    user = postfix
    password = postfixpass
    hosts = localhost
    dbname = postfix
    query          = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
    #query          = SELECT domain FROM domain WHERE domain='%s'
    #optional query to use when relaying for backup MX
    #query           = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
    #expansion_limit = 100

    /etc/postfix/sql/mysql_virtual_alias_maps.cf:

    user = postfix
    password = postfixpass
    hosts = localhost
    dbname = postfix
    query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
    #expansion_limit = 100

    /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf:

    user = postfix
    password = postfixpass
    hosts = localhost
    dbname = postfix
    query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'

    /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf:

    user = postfix
    password = postfixpass
    hosts = localhost
    dbname = postfix
    query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' AND mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'

    /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf:

    # handles catch-all settings of target-domain
    user = postfix
    password = postfixpass
    hosts = localhost
    dbname = postfix
    query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' AND alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'

    /etc/postfix/sql/mysql_virtual_mailbox_maps.cf:

    user = postfix
    password = postfixpass
    hosts = localhost
    dbname = postfix
    query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
    #expansion_limit = 100

    Немного безопасности:

    chmod 640 /etc/postfix/sql/*
    chown -R postfix /etc/postfix/sql

    Правим /etc/postfix/master.cf:

    ...
    pickup    fifo  n       -       -       60 1       pickup
        -o content_filter=
        -o receive_override_options=no_header_body_checks
    ...
    smtp-amavis     unix    -       -       -       -       2       smtp
        -o smtp_data_done_timeout=1200
        -o smtp_send_xforward_command=yes
        -o disable_dns_lookups=yes
        -o max_use=20
    127.0.0.1:10025 inet    n       -       -       -       -       smtpd
        -o content_filter=
        -o local_recipient_maps=
        -o relay_recipient_maps=
        -o smtpd_restriction_classes=
        -o smtpd_delay_reject=no
        -o smtpd_client_restrictions=permit_mynetworks,reject
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o smtpd_data_restrictions=reject_unauth_pipelining
        -o smtpd_end_of_data_restrictions=
        -o mynetworks=127.0.0.0/8
        -o smtpd_error_sleep_time=0
        -o smtpd_soft_error_limit=1001
        -o smtpd_hard_error_limit=1000
        -o smtpd_client_connection_count_limit=0
        -o smtpd_client_connection_rate_limit=0
        -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
    dovecot unix    -       n       n       -       -      pipe
        flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -n -m ${extension}

    3. Настройка Amavisd-new+ClamAV+SpamAssassin

    Правим /etc/amavis/conf.d/05-node_id:

    ...
    $myhostname = "mail.example.com"
    ...

    Правим /etc/amavis/conf.d/15-content_filter_mode (точнее раскомментируем соответствующие строчки):

    ...
    @bypass_virus_checks_maps = (
       \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
    ...
    @bypass_spam_checks_maps = (
       \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

    Правим /etc/amavis/conf.d/21-ubuntu_defaults в соответствиями со своими желаниями:

    ...
    $final_virus_destiny      = D_DISCARD;
    $final_banned_destiny     = D_DISCARD;
    $final_spam_destiny       = D_PASS;  # Только помечаем обнаруженный спам
    $final_bad_header_destiny = D_PASS;  # Только помечаем письмо с плохими заголовками
    ...

    Правим /etc/amavis/conf.d/50-user:

    ...
    # Добавляем поддержку виртуальных доменов в MySQL
    @lookup_sql_dsn = (
    ['DBI:mysql:database=postfix;host=127.0.0.1;port=3306',
         'postfix',
         'postfixpass']);
    .....
    $sql_select_policy = 'SELECT domain FROM domain WHERE CONCAT("@",domain) IN (%k)';
    ...

    Немного безопасности:

    chmod 640 /etc/amavis/conf.d/50-user

    Добавляем в /etc/clamav/freshclam.conf:

    ...
    NotifyClamd /etc/clamav/clamd.conf

    Добавляем сервисных пользователей в группы:

    adduser clamav amavis
    adduser amavis clamav

    Правим /etc/default/spamassassin:

    ENABLED=1
    ...
    CRON=1

    Перезапускаем сервисы:

    /etc/init.d/postfix restart
    /etc/init.d/amavis restart
    /etc/init.d/clamav-freshclam restart
    /etc/init.d/clamav-daemon restart

    4. Настройка Dovecot (IMAP,POP3,LDA)

    Правим /etc/dovecot/dovecot.conf:

    ...
    protocols = imap imaps pop3 pop3s
    disable_plaintext_auth = no
    ...
    mail_location = maildir:/home/vmail/%d/%u
    ...
    # !!! Не забываем проверить uid для vmail и gid для mail !!!
    mail_uid = 111
    mail_gid = 8
    ...
    first_valid_uid = 111
    last_valid_uid = 111
    first_valid_gid = 8
    last_valid_gid = 8
    ...
    protocol imap {
    ...
         mail_plugins = quota imap_quota
         imap_client_workarounds = delay-newmail netscape-eoh
    }
    protocol pop3 {
    ...
         mail_plugins = quota
         pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
    }
    protocol lda {
    ...
         postmaster_address = postmaster@example.com
         mail_plugins = quota
    }
    ...
    auth_default_realm = example.com
    auth default {
         mechanisms = plain login
         passdb sql {
           args = /etc/dovecot/dovecot-sql.conf
    }
         userdb sql {
           args = /etc/dovecot/dovecot-sql.conf
    }
    ...
         socket listen {
           path = /var/run/dovecot/auth-master
           mode = 0600
           user = vmail
           group = mail
    }
    }
    ...
    plugin {
       quota = maildir:User quota
    # Квота по умолчанию, затем переопределяется SQL-запросом userdb
       quota_rule = storage=50M:messages=1000
    # Дополнительная квота к корзине, чтобы можно было удалять сообщения при превышении квоты
       quota_rule2 = Trash:storage=10M
    # Сообщение об исчерпании 80% квоты
       quota_warning = storage=80%% /usr/local/bin/quota-warning.sh 80
       ...
    }

    Правим /etc/dovecot/dovecot-sql.conf:

    ...
    driver = mysql
    connect = host=127.0.0.1 dbname=postfix user=postfix password=postfixpass
    # Не забываем про uid и gid
    password_query = SELECT username as user, password, concat('/home/vmail/', maildir) as userdb_home, concat('maildir:/home/vmail/', maildir) as userdb_mail, 111 as userdb_uid, 8 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
    user_query = SELECT concat('/home/vmail/', maildir) as home, concat('maildir:/home/vmail/', maildir) as mail, 111 AS uid, 8 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
    ...

    Копируем dovecot.conf в dovecot-nowarning.conf и комментируем строчку:

    ...
    # Необходимо во избежание цикла
    #quota_warning = storage=80%% /usr/local/bin/quota-warning.sh 80
    ...

    Создаем /usr/local/bin/quota-warning.sh:

    #!/bin/sh
    PERCENT=$1
    cat << EOF | /usr/lib/dovecot/deliver -d $USER -c /etc/dovecot/dovecot-nowarning.conf
    From: postmaster@example.com
    Subject: quota warning
    Your mailbox is now $PERCENT% full. Please delete unnecessary emails.
    EOF

    На всякий случай устанавливаем бит выполнения на скрипты:

    chmod +x /usr/local/bin/*.sh

    Перезапускаем сервис:

    /etc/init.d/dovecot restart

    5. Установка Roundcube

    Качаем и распаковываем последнюю версию:

    cd /var/www
    wget ROUNDCUBE_URL
    tar -xvzf roundcubemail-X.X.X.tar.gz
    mv roundcubemail-X.X.X mail
    chown -R www-data:www-data mail

    Создаем базу данных для Roundcube:

    mysql -u root -p
    >CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
    >GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost IDENTIFIED BY 'password';
    >FLUSH PRIVILEGES;
    cd /var/www/mail
    mysql -u root -p roundcubemail < SQL/mysql.initial.sql

    Идем на http://example.com/mail/installer/ и следуем инструкциям.

    Удаляем каталог installer:

    rm -r /var/www/mail/installer

    Правим /var/www/mail/config/main.inc.php в соответствии с нуждами, например:

    ...
    $rcmail_config['default_host'] = 'localhost';
    $rcmail_config['smtp_server'] = 'localhost';
    $rcmail_config['smtp_port'] = 25;
    $rcmail_config['smtp_user'] = '';
    $rcmail_config['smtp_pass'] = '';
    $rcmail_config['enable_caching'] = false;
    $rcmail_config['login_lc'] = true;
    $rcmail_config['auto_create_user'] = true;
    $rcmail_config['dont_override'] = array('skin','default_imap_folders','keep_alive');
    $rcmail_config['identities_level'] = 3;
    $rcmail_config['create_default_folders'] = true;
    $rcmail_config['protect_default_folders'] = true;
    $rcmail_config['spellcheck_languages'] = array('en'=>'English');
    $rcmail_config['preview_pane'] = true;
    $rcmail_config['skip_deleted'] = true;
    ...

    По умолчанию, Apache в Ubuntu не обрабатывает .htaccess в директории /var/www, поэтому правим /etc/apache2/sites-available/default:

    <Directory /var/www/>
       Options Indexes FollowSymLinks MultiViews
       AllowOverride All
       Order allow,deny
       allow from all
    </Directory>

    Перезапускаем Apache:

    /etc/init.d/apache2 restart

    На этом основная настройка почтовой системы закончена, остается создавать домены, почтовые ящики, проверить отсылку/чтение почты. Важное DNS-замечание: необходимо не забыть прописать MX-запись для домена (example.com) в виде mail.example.com и A-запись для mail.example.com, чтобы почта корректно стала ходить извне.

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

    .

    Счетчик тИЦ и PR Яндекс.Метрика Msn bot last visit powered by MyPagerank.NetYahoo bot last visit powered by MyPagerank.Net ping fast  my blog, website, or RSS feed for Free