В данной статье будет рассмотрена установка почтового сервера на
FreeBSD с поддержкой виртуальных доменов в связке postfix +
courier-imap + mysql с возможностью фильтрации и доставки почты через
maildrop и защитой от спама и вирусов с помощью spamassasin и dr.web.
Для начала создадим базу mysql, откуда postfix будет брать данные.
Создаем файл postfix.sql
USE mysql;
INSERT INTO user (Host, User, Password) VALUES (`localhost`,`postfix`,password(`postfix`));
INSERT INTO db (Host, Db, User, Select_priv) VALUES (`localhost`,`postfix`,`postfix`,`Y`);
CREATE DATABASE postfix;
USE postfix;
# Транспортная таблица, подробнее о формате - man transport.
CREATE TABLE transport (
# Имя домена
domain varchar(128) NOT NULL default ``,
# Используемый транспорт. Например "local:" - для локальной доставки,
# "maildrop:" - для виртуальных доменов с фильтрацией почты, "virtual:" - для
# виртуальных доменов без фильтрации.
destination varchar(128) NOT NULL default ``,
UNIQUE KEY domain (domain)
) TYPE=MyISAM
CREATE TABLE alias (
address varchar(255) NOT NULL default ``,
goto text NOT NULL,
domain varchar(255) NOT NULL default ``,
create_date datetime NOT NULL default `0000-00-00 00:00:00`,
change_date datetime NOT NULL default `0000-00-00 00:00:00`,
active tinyint(4) NOT NULL default `1`,
PRIMARY KEY (address)
) TYPE=MyISAM
CREATE TABLE domain (
domain varchar(255) NOT NULL default ``,
description varchar(255) NOT NULL default ``,
create_date datetime NOT NULL default `0000-00-00 00:00:00`,
change_date datetime NOT NULL default `0000-00-00 00:00:00`,
active tinyint(4) NOT NULL default `1`,
PRIMARY KEY (domain)
) TYPE=MyISAM
CREATE TABLE mailbox (
# Адрес пользователя в формате "user@domain"
username varchar(255) NOT NULL default ``,
# Пароль в plaintext для возможности использования courier`ом cram-md5 шифрования
password varchar(255) NOT NULL default ``,
# Общая информация о пользователе.
name varchar(255) NOT NULL default ``,
# Название почтового ящика в формате "user@domain/"
maildir varchar(255) NOT NULL default ``,
create_date datetime NOT NULL default `0000-00-00 00:00:00`,
change_date datetime NOT NULL default `0000-00-00 00:00:00`,
# Квота. Может быть формата "<число>S" или "<числоC>" или "<число>S,<число>C",где S означает
# общий размер ящика, а C - кол-во писем (например "500000S" или "500000S,20000C")
quota tinytext NOT NULL default ``,
# Поле активности, используется для разрешения или отказа в доступе к сервисам smtp и pop/imap
active tinyint(4) NOT NULL default `1`,
PRIMARY KEY (username)
) TYPE=MyISAM
INSERT INTO transport (domain, destination) VALUES (`test.local.net`, `maildrop:`);
INSERT INTO domain (domain,description) VALUES (`test.local.net`,`Test Domain`);
INSERT INTO alias (address,goto) VALUES (`alias@test.local.net`, `user@test.local.net`);
INSERT INTO mailbox (username,password,name,maildir,quota) VALUES (`user@test.local.net`, `test`, `Test user`, `test@test.local.net/`, `500000S`);
Перезагрузите mysql
mysqladmin reload
Установка postfix
cd /usr/ports/security/cyrus-sasl2
make WITH_MYSQL_VER=3 WITHOUT_OTP=yes WITHOUT_NTML=yes install clean
опция WITH_MYSQL_VER зависит от установленной версии mysql (в моем
случае 3.23.57)
cd /usr/ports/mail/postfix && make install clean
При установке в меню выбираем поддержку SASL2, TLS и MYSQL.
После установки
newaliases
cp /usr/local/etc/postfix/main.cf.default /usr/local/etc/postfix/main.cf
chmod 750 /usr/local/etc/postfix
chgrp postfix /usr/local/etc/postfix
Открываем main.cf и вносим туда следущие значения
disable_vrfy_command = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = mysql:/usr/local/etc/postfix/mysql_sasl.cf
smtp_sasl_security_options = noanonymous, noplaintext, noactive, nodictionary
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks, \
reject_invalid_hostname, \
reject_unknown_hostname, \
reject_non_fqdn_hostname
smtpd_recipient_restrictions = permit_mynetworks, \
permit_sasl_authenticated, \
reject_unauth_destination, \
reject_unknown_recipient_domain, \
reject_non_fqdn_recipient, \
reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sender_restrictions = permit_mynetworks, \
permit_sasl_authenticated, \
reject_unknown_sender_domain, \
reject_rhsbl_sender dsn.rfc-ignorant.org
transport_maps = mysql:/usr/local/etc/postfix/mysql_transport.cf
virtual_alias_maps = mysql:/usr/local/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:1005
virtual_mailbox_base = /var/spool/virtual
virtual_mailbox_domains = mysql:/usr/local/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_mailbox_limit = 51200000
virtual_minimum_uid = 1001
virtual_uid_maps = static:1005
Обратите внимание что virtual uid и gid имеют статическую привязку и
эти значения следует изменить на uid и gid юзера от которого будеть
работать maildrop.
В моем случае это юзер vmail с uid и gid 1005.
Транспорт virtual не поддерживает квоты, в отличии от maildrop,
поэтому если вы хотите включить поддержку квот для virtual, установите
патч http://www.oav.net/vda/
Создаем нужные конфигурационные файлы и директории.
pw useradd vmail -d /var/spool/virtual -s /sbin/nologin
mkdir -m 700 /var/spool/virtual
chown vmail:vmail /var/spool/virtual
mysql_transport.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
table = transport
select_field = destination
where_field = domain
mysql_virtual_alias_maps.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
table = alias
select_field = goto
where_field = address
mysql_virtual_domains_maps.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
table = domain
select_field = description
where_field = domain
mysql_virtual_mailbox_maps.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
table = mailbox
select_field = maildir
where_field = username
additional_conditions = and active = `1`
mysql_sasl.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
table = mailbox
select_field = password
where_field = username
additional_conditions = and active = `1`
Создаем файл /usr/local/lib/sasl2/smtpd.conf
pwcheck_method: auxprop
auxprop_plugin: mysql
mysql_user: postfix
mysql_passwd: postfix
mysql_hostnames: localhost
mysql_database: postfix
mysql_statement: select password from mailbox where username=`%u@%r`
Далее
chmod 750 /usr/local/lib/sasl2
chgrp mail /usr/local/lib/sasl2
Веб-интерфейс для администрирования виртуальных доменов (можно взять
как образец) http://high5.net/postfixadmin/Установка maildrop
maildrop является альтернативой широко используемому procmail и имеет
гораздо большие возможности - поддержка mysql и ldap, поддержка квот,
более мощный язык фильтрации, повышенная безопасность, поддержка
формата Maildir++.
Более подробная документации в директории /usr/local/share/doc/maildrop
cd /usr/ports/mail/maidrop
Открываем Makefile и меняем
CONFIGURE_ARGS+= --enable-syslog=1 \
--enable-use-flock \
--with-etcdir="${PREFIX}/etc" \
--enable-maildrop-uid="${MAILDROP_SUID}" \
--enable-maildrop-gid="${MAILDROP_SGID}" \
на
CONFIGURE_ARGS+= --enable-syslog=1 \
--enable-use-flock \
--with-etcdir="${PREFIX}/etc" \
--enable-maildrop-uid="${MAILDROP_SUID}" \
--enable-maildrop-gid="${MAILDROP_SGID}" \
--with-trashquota \
--enable-maildropmysql \
--with-mysqlconfig="${PREFIX}/etc/maildrop.config"
Далее
make WITH_MAILDIRQUOTA=yes install clean
После сборки запустите maildrop -v. Должны быть следующие строки
Maildir quota extension enabled.
Virtual user database via MySQL extension enabled.
В /usr/local/etc/postfix/master.cf измените конфиг maildrop на
maildrop unix - n n - - pipe
flags=Rhu user=vmail argv=/usr/local/bin/maildrop -w 90 -d ${recipient}
Создаем файл /usr/local/etc/maildrop.config со следующим содержанием
hostname localhost
port 3306
database postfix
dbuser postfix
dbpw postfix
dbtable mailbox
default_uidnumber 1005
default_gidnumber 1005
uid_field username
uidnumber_field 1005 # vmail
gidnumber_field 1005 # vmail
maildir_field maildir
homedirectory_field `/var/spool/virtual`
quota_field quota
mailstatus_field active
where_clause "where active = `1`"
Создаем файл /var/spool/virtual/.mailfilter со следующим содержанием
UMASK=077
LOGNAME=tolower($LOGNAME)
include "$HOME/.mailfilters/$LOGNAME"
Ставим права на запись и чтение только пользователю иначе maildrop
откажется работать.
chmod 600 /var/spool/virtual/.mailfilter
chown vmail:vmail /var/spool/virtual/.mailfilter
Создаем директорию /var/spool/virtual.mailfilters
mkdir -m 700 /var/spool/virtual/.mailfilters
chown vmail:vmail /var/spool/virtual/.mailfilters
Создаем include файл в формате user@domain соотвествующему переменной
$LOGNAME /var/spool/virtual/.mailfilters/user@test.local.net со
следующим содержанием
if ("/^X-Spam-Flag:.YES/")
{
to "$HOME/$LOGNAME/.Spam"
}
to "$HOME/$LOGNAME"
NB! В отличии от virtual maildrop сам не создает maildir, поэтому
следует создать нужный вам maildir и subfolders используя утилиту
maildirmake
su -fm vmail -c `maildirmake /var/spool/virtual/user@test.local.net`
su -fm vmail -c `maildirmake -f Spam /var/spool/virtual/user@test.local.net`
Файл .mailfilter - это файл дает возможность maildrop выбрать нужный
конфиг для пользователя, используя его логин, который берется из
переменной $LOGNAME (user@domain).
В директории .mailfilters хранятся конфиги для каждого виртуального
юзера.
Maildrop будет искать конфиг в формате user@domain и использовать его.
Можно написать скрипт, который при создании maildir, автоматически
создает нужный конфиг с дефолтными опциями в .mailfilters.
В данном примере maildrop отбирает почту с заголовком X-Spam-Flag:
YES, который генерирует spamassassin, установка которого будет
рассмотрена ниже, и кладет ее в папку Spam. Остальная почта
направляется в INBOX.
Примеры фильтров для maildrop можно найти на
http://sourceforge.net/projects/mdropspammailfilter
Создаем файл /usr/local/etc/quotawarnmsg
From: Mail Delivery System <mailto:Mailer-Daemon@REMOVE-THIS-FAKE.test.local.net>
Reply-To: root
To: Dear User
Subject: Mail quota warning
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
Your mailbox on the server is now more than 90% full. So that you can continue
to receive mail you need to remove some messages from your mailbox.
Данное письмо будет направляться пользователю, если обьем его
почтового ящика превысил 90%. Процент можно выставлять через опцию
maildrop -w % в postfix master.cf.
Установка Courier-imap
cd /usr/ports/mail/courier-imap && make WITH_CRAM=yes WITH_MYSQL=yes install clean
chmod 700 /usr/local/etc/courier
chmod 750 /usr/local/var/authdaemon
chgrp vmail /usr/local/var/authdaemon
Правим /usr/local/etc/courier/authmysqlrc
Для доступа к спулу почты /var/spool/virtual courier работает от юзера
vmail (uid 1005,gid 1005)
#DEFAULT_DOMAIN domain.tld
MYSQL_CLEAR_PWFIELD password
MYSQL_DATABASE postfix
MYSQL_GID_FIELD `1005`
MYSQL_HOME_FIELD `/var/spool/virtual`
MYSQL_LOGIN_FIELD username
MYSQL_MAILDIR_FIELD maildir
MYSQL_NAME_FIELD name
MYSQL_OPT 0
MYSQL_PASSWORD postfix
MYSQL_PORT 3306
MYSQL_QUOTA_FIELD quota
MYSQL_SERVER localhost
MYSQL_UID_FIELD `1005`
MYSQL_USERNAME postfix
MYSQL_USER_TABLE mailbox
MYSQL_WHERE_CLAUSE active=`1`
Убедитесь что использована табуляция а не пробелы, иначе конфиг не
будет работать.
Создаем SSL сертификат
mkimapdcert
В imapd.conf меняем
TCPDOPTS="-nodnslookup -noidentlookup"
на
TCPDOPTS="-nodnslookup -noidentlookup -user=vmail"
IMAP_CAPABILITY_ORIG="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT
THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=CRAM-SHA1 IDLE"
Установка SpamAssassin
cd /usr/ports/mail/p5-Mail-SpamAssassin && make install clean
В данном примере настройки пользователей будут хранится в базе mysql
Открываем /usr/local/share/doc/p5-Mail-SpamAssassin/spamassassin.sql и
добавляем в начало
CREATE DATABASE spamassassin;
USE spamassassin;
Далее выполняем
mysql < /usr/local/share/doc/p5-Mail-SpamAssassin/spamassassin.sql
Будет создана база spamassassin, где хранятся настройки пользователей.
Назначаем права на доступ к базе для юзера spamd
mysql
mysql> GRANT SELECT INSERT DELETE UPDATE ON spamassassin.* TO spamd@localhost I
DENTIFIED BY `spamd`;
Создаем юзера spamd от которого будет работать SA.
pw useradd spamd -d /var/spool/spamd -s /sbin/nologin
Создаем домашнюю директорию для Razor DCC и Pyzor.
mkdir -m 750 /var/spool/spamd
chown spamd /var/spool/spamd
Создаем файл /usr/local/etc/mail/spamassassin/local.cf
rewrite_subject 1
report_safe 0
use_terse_report 0
use_bayes on
auto_learn 1
skip_rbl_checks 0
use_razor2 1
use_DCC 1
use_pyzor 0
dcc_add_header 1
dns_available yes
# Секция для mysql
user_scores_dsn DBI:mysql:spamassassin:localhost
user_scores_sql_username spamd
user_scores_sql_password spamd
user_scores_sql_table userpref
В скрипте для запуска SA /usr/local/etc/rc.d/spamd.sh
case "$1" in
start)
[ -x ${PREFIX}/bin/spamd ] && ${PREFIX}/bin/spamd -u spamd \
-r /var/run/spamd -H /var/spool/spamd -x -a -Q -L -m 16 -d && echo -n ` spamd`
Веб-интерфейс для SA можно скачать отсюда:
http://spamassassin.org/devel/php-sa-mysql-0.5.tar.gz (PHP)
http://spamassassin.org/devel/sa-user-admin-0.1.tar.gz (CGI)
Установка Drweb
cd /usr/ports/security/drweb-postfix
При установке порта в distinfo была указана версия
drweb-clients-4.29.12-D-sources.tar.gz, которой уже не было на
фтп-сервере drweb.
Поэтому я скачал последнюю на данный момент версию
drweb-clients-4.29.12-F-sources.tar.gz с ftp://ftp.drweb.ru/pub/unix
В Makefile изменил
DISTNAME= drweb-clients-4.29.12-D-sources
на
DISTNAME= drweb-clients-4.29.12-F-sources
Далее
md5 /usr/ports/distfiles/drweb-clients-4.29.12-F-sources.tar.gz | sed `s/\/usr\
/ports\/distfiles\///` > distinfo
make install clean
После установки отредактируйте файлы
/usr/local/etc/drweb/drweb_postfix.conf и /usr/local/drweb/drweb32.ini.
В моем случае drwebd работал через unix сокет.
В /usr/local/etc/postfix/master.cf меняем
smtp inet n - n - 20 smtpd
на
smtp inet n - n - 20 smtpd -o content_filter=spam
Создаем транспорт spam
spam unix - n n - 5 pipe
flags=Rq user=drweb argv=/usr/local/bin/spamc -u mailnull \
-e /usr/local/sbin/drweb-postfix \
--conf=/usr/local/etc/drweb/drweb_postfix.conf -f ${sender} -- ${recipient}
В данном примере spamc запускается от sendmail`овского mailnull
(который без толку висел в /etc/passwd :) )
Принцип работы данной конструкции: почта направляется к spamd клиентом
SA spamc...проверяется на спам, далее направляется к drwebd клиентом
drweb_postfix и проверяется на наличие вирусов.
Запускаем сервисы
postfix start
/usr/local/etc/rc.d/drweb-0.sh start
/usr/local/etc/rc.d/spamd.sh start
/usr/local/etc/rc.d/courier-imap-imapd.sh start
Вывод sockstat -l
root master 30043 11 tcp4 *:25 *:*
vmail couriertcp 25437 6 tcp4 *:143 *:*
spamd perl 23513 5 tcp4 127.0.0.1:783 *:*
drweb drwebd 266 3 stream /usr/local/drweb/run/drwebd.sock
Отправляем тестовое письмо юзеру user@test.local.net
echo `X-Spam-Flag: YES` | mail user@test.local.net
и смотрим в /var/log/maillog
postfix/smtpd[30072]: connect from test1.local.net[192.168.0.2]
postfix/smtpd[30072]: DDAFDA3: client=test1.local.net[192.168.0.2]
postfix/cleanup[30073]: DDAFDA3: message-id=<mailto:20030811104104.30F2D115@REMOVE-THIS-FAKE.test1.local.net>
postfix/qmgr[30071]: DDAFDA3: from=<mailto:user@REMOVE-THIS-FAKE.test1.local.net>, size=466, nrcpt=1 (queue active)
postfix/smtpd[30072]: disconnect from test1.local.net[192.168.0.2]
server spamd[23513]: connection from localhost [127.0.0.1] at port 56559
server spamd[30081]: processing message <mailto:20030811104104.30F2D115@REMOVE-THIS-FAKE.test1.local.net> for mailnull:1017.
server spamd[30081]: clean message (0.1/5.0) for mailnull:1017 in 5.1 seconds,485 bytes.
server drweb-postfix: dwlib: scan[30080]: message(/tmp/drweb.tmp.3qN7Z2) sent by user@test1.local.net is passed
server postfix/pickup[30070]: D685C7AF: uid=426 from=<mailto:user@REMOVE-THIS-FAKE.test1.local.net>
server postfix/cleanup[30073]: D685C7AF: message-id=<mailto:20030811104104.30F2D115@REMOVE-THIS-FAKE.test.local.net>
server postfix/pipe[30079]: DDAFDA3: to=<mailto:user@REMOVE-THIS-FAKE.test.local.net>, relay=spam, delay=13, status=sent (test.local.net)
server postfix/qmgr[30071]: D685C7AF: from=<mailto:user1@REMOVE-THIS-FAKE.test1.local.net>, size=734, n
rcpt=1 (queue active)
server postfix/virtual[30088]: D685C7AF: to=<mailto:user@REMOVE-THIS-FAKE.test.local.net>, relay=maildrop, delay=1, status=sent (maildir)
Пробуем забрать почту с ящика с помощью fetchmail или утилиты imtest,
которая входит в порт /usr/ports/mail/cyrus-imap.
imtest -m cram-md5 -a user@test.local.net -w test localhost
S: * OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT
THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=CRAM-SHA1 IDLE XCOURIEROUTBOX=I
NBOX.Outbox] Courier-IMAP ready.
C: C01 CAPABILITY
S: * CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THRE
AD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=CRAM-SHA1 IDLE XCOURIEROUTBOX=INBOX.Outbox
S: C01 OK CAPABILITY completed
C: A01 AUTHENTICATE CRAM-MD5
S: + PDlBNjY2N0E2MzAyRTcyQzE4ODU0NjE3MkNBQUQ5Q0FDQHVuaXgubG9jYWwubmV0Pg==
C: dXNlckB0ZXN0Mi5sb2NhbC5vcmcgYzcwNTdjNWJlNWQ5MzllYTU0ZDg3NTJmZTdjMGI5ZjA=
S: A01 OK LOGIN Ok.
Authenticated.
Security strength factor: 0
C: A1 LIST "" *
LIST (\HasNoChildren) "." "INBOX.Spam"
LIST (\Unmarked \HasChildren) "." "INBOX"
S: A1 OK LIST completed.
C: A2 STATUS INBOX.Spam (MESSAGES)
STATUS "INBOX.Spam" (MESSAGES 1)
S: A2 OK STATUS Completed.
C: A3 FETCH 1 FULL
Проверяем smtp auth:
printf `test\0test\0test` | mmencode (формат -
"username\0username\0password")
dGVzdAB0ZXN0AHRlc3Q= (запомните этот пароль или скопируйте в буфер)
Соединяемся с удаленного хоста (не с localhost :)).
telnet test.local.net 25
Trying 127.0.0.1...
Connected to test.local.net.
Escape character is `^]`.
220 test.local.net ESMTP Postfix
EHLO test
250-test.local.net
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5
250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5
250-XVERP
250 8BITMIME
MAIL FROM:
250 Ok
RCPT TO:
554 : Relay access denied
QUIT
Повторяем попытку
telnet test.local.net 25
Trying 127.0.0.1...
Connected to test.local.net.
Escape character is `^]`.
220 test.local.net ESMTP Postfix
EHLO test
250-test.local.net
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5
250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5
Вводим:
AUTH PLAIN dGVzdAB0ZXN0AHRlc3Q=
235 Authentication successful
MAIL FROM:
250 Ok
RCPT TO:
250 Ok
DATA
Замечания и пожелания по данной статье просьба присылать на leech@alpha.sytes.net