magnify
Home arrow 2011 arrow Август
formats

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

Опубликовано: 04.08.2011 Автор: в

Недавно пришлось настраивать почтовую систему начального уровня, поэтому решил написать небольшое 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, грейлистинг, проверка заголовков и др., тем более, что реализуются они сравнительно просто.

Данная запись писалась по горячим следам, вполне возможно, что некоторые детали могли быть упущены, поэтому, как говорится, /var/log/ в помощь..8)

UPDATE 06.12.2012: в Ubuntu >= 12.04 уже идет Dovecot 2.0, и там конфигурация разбита на файлы. В целом, настройка повторяется с учетом этого, также некоторые конфигурационные директивы меняются, в частности imaps и pop3s указывать не надо, есть файл ssl.conf, формат квоты в плагине также немного меняется, все это легко адаптируется по документации для Dovecot 2.x. Лично у меня эта адаптация заняла не больше 15 минут.

 
Просмотров: 18 181 | 21 комментарий  comments