|
|
www.lissyara.su
—> статьи
—> FreeBSD
—> почтовые системы
—> Почтовый сервер по шагам ч.3
Почтовый сервер по шагам ч.3
Автор: KontraBass.
Итак, продолжим.
Добавим еще,
main.cf
smtpd_recipient_restrictions =
#reject_non_fqdn_recipient
#reject_non_fqdn_sender
#reject_unknown_sender_domain
#check_recipient_access hash:/usr/local/etc
/postfix/restrictions/rej_int_recipient.hash
#check_recipient_access hash:/usr/local/etc
/postfix/restrictions/rej_group_recipient.hash
#permit_mynetworks
#reject_unauth_destination
#check_client_access cidr:/usr/local/etc
/postfix/restrictions/permit_for_ip.cidr
#reject_non_fqdn_helo_hostname
reject_invalid_helo_hostname
#reject_unknown_helo_hostname
#reject_unknown_client_hostname
#check_sender_mx_access cidr:/usr/local/etc
/postfix/restrictions/bogus_mx.cidr
#check_sender_access hash:/usr/local/etc
/postfix/restrictions/external_sender_check.hash
#check_helo_access pcre:/usr/local/etc
/postfix/restrictions/helo.pcre
#check_client_access pcre:/usr/local/etc
/postfix/restrictions/client.pcre
sleep 1, reject_unauth_pipelining
permit
| Добавили отказ слишком торопящихся клиентов. Проверить сложно. искать спамерский софт..
Шаг 21 Postgrey
Чем еще утяжелить жизнь спамеров? можно postgrey, что это, проще прочитать в википедии.
Приступим.
cd /usr/ports/mail/postgrey/
make install && make clean
echo 'postgrey_enable="YES"' >> /etc/rc.conf
/usr/local/etc/rc.d/postgrey start
|
Можно поднастроить этот сервис под себя, кстати он кидает свои файлы, типа белых листов, в /usr/local/etc/postfix/. На досуге заглянуть.
netstat -na | grep LIST
tcp4 0 0 127.0.0.1.10023 *.* LISTEN
tcp6 0 0 ::1.10023 *.* LISTEN
|
упс, собрал с ipv6.. может лучше сокет?
(для ipv4 check_policy_service inet:127.0.0.1:10023)
echo 'postgrey_flags="--unix=/tmp/postgrey.sock"' >> /etc/rc.conf
/usr/local/etc/rc.d/postgrey restart
ls -al /tmp/postgrey.sock
srw-rw-rw- 1 postgrey postgrey 0 Dec 11 00:51 /tmp/postgrey.sock
|
сервисы на порту 10023 пропали.
main.cf
smtpd_recipient_restrictions =
#reject_non_fqdn_recipient
#reject_non_fqdn_sender
#reject_unknown_sender_domain
#check_recipient_access hash:/usr/local/etc
/postfix/restrictions/rej_int_recipient.hash
#check_recipient_access hash:/usr/local/etc
/postfix/restrictions/rej_group_recipient.hash
#permit_mynetworks
#reject_unauth_destination
#check_client_access cidr:/usr/local/etc
/postfix/restrictions/permit_for_ip.cidr
#reject_non_fqdn_helo_hostname
#reject_invalid_helo_hostname
#reject_unknown_helo_hostname
#reject_unknown_client_hostname
#check_sender_mx_access cidr:/usr/local/etc
/postfix/restrictions/bogus_mx.cidr
#check_sender_access hash:/usr/local/etc
/postfix/restrictions/external_sender_check.hash
#check_helo_access pcre:/usr/local/etc
/postfix/restrictions/helo.pcre
#check_client_access pcre:/usr/local/etc
/postfix/restrictions/client.pcre
#sleep 1, reject_unauth_pipelining
check_policy_service unix:/tmp/postgrey.sock
permit
| рестартуем, неплохо бы проверить как работает ... Настраиваем клиент на отправку на порт 25 и вперед
/usr/local/etc/rc.d/postfix restart
|
Шаг 22 multi_recipient & вложения
Еще кое-что, добавим ограничение -нельзя слать "ответы" о недоставке,.. множеству получателям. Добавляется в строго определенном разделе
main.cf
smtpd_data_restrictions =
reject_multi_recipient_bounce
|
/usr/local/etc/rc.d/postfix restart
|
Запретим еще пересылку всяких непонятных вложений..
посмотрим сначала,
postconf | grep header_checks
header_checks =
lmtp_header_checks =
mime_header_checks = $header_checks
|
по умолчанию настройка одна
main.cf
header_checks = pcre:/usr/local/etc
/postfix/restrictions/header.pcre
| перенос строки это только зесь..
restrictions/header.pcre
/name=\"(.*)\.+?(669|aac|acm|aif|aiff|amf|asf|au|avi|ax|b64
|bas|bat|bhx|bin|bpl|cat|chm|cmd|com|cpl|dll|dpl|drv|emf
|exe|far|grp|hlp|hqx|inf|ini|ins|it|itz|js|jse|kar|lha
|lnk|m2v|m3u|m4a|mda|mdb|mde|mdt|mdw|mdz|mid|midi|mim
|miz|mmf|mod|mov|mp1|mp2|mp3|mp4|mpeg|mpg|msc|msc|msi
|msp|mst|mtm|nls|nsa|nst|nsv|ocx|ogg|okt|olb|ole|ops
|pif|pls|prg|ptm|qt|reg|rmi|rom|s3m|s3z|scr|snd|stm
|stz|sys|tlb|ult|vb|vbs|voc|vxd|waw|wma|wmf|wmv|wsc
|wsf|wsh|xm|xmz)+?(.*)*?\"$/x
REJECT Sorry attached file $1.$2.$3 is blocked.
# это все одна строка
| Да, уж. Может уже проще разрешить только определенные?
postmap restrictions/header.regexp
/usr/local/etc/rc.d/postfix restart
|
С ораничениями пока хватит, конечно еще немало можно набить здесь всякого, как минимум rbl списки.., это уже по желанию, в инете много инструкций как это сделать и споров о их честности|надежности|эффективности.
Важно! не забыть раскомментировать все наши великие ограничения.
Шаг 23 Clamav
Зачем? Ну, проверку на вирусы неплохо бы иметь. А если в наличии не имеется продукта от какого нить именитого производителя? Ставим по желанию.
cd /usr/ports/security/clamav
make install && make clean
|
[X} ARC
[X} ARJ
[X} DMG_XAR
[X} DOCS
[ } EXPERIMENTAL
[ } ICONV
[ } IPV6
[ } LDAP
[X} LHA
[X} LLVM
[ } MILTER
[ } STDERR
[ } TESTS
[X} UNRAR
[X} UNZOO
| из опций все вроде понятно - поддержка архивов, лдап не нужен, милтер тоже (подключаться будем не как милтер), LHA и LLVM понятия не имею что такое, трогать не будем ;(.
после завершения можно порыться в его конфиге, /usr/local/etc/clamd.conf там все понятно расписано. Я не трогал, на досуге.. Сразу сам не запустится, потребует баз. ОК. Вместе с clamav-ом поставилась утилита обновления баз clamav_freshclam. Конфиг тоже можно глянуть - /usr/local/etc/freshclam.conf
echo 'clamav_clamd_enable="YES"' >> /etc/rc.conf
echo 'clamav_freshclam_enable="YES"' >> /etc/rc.conf
/usr/local/etc/rc.d/clamav-freshclam start
sleep 40
/usr/local/etc/rc.d/clamav-clamd start
|
сразу бы неплохо заглянуть в /var/log/clamav/clamd.log и /var/log/clamav/freshclam.log, и если все в порядке, двигаемся дальше.
Для переправки писем на проверку антивирусу поставим clamsmtpd.
cd /usr/ports/security/clamsmtp/
make install && make clean
|
опции не замысловаты.
cd /usr/local/etc/
cp clamsmtpd.conf{-sample,}
|
clamsmtpd.conf
OutAddress: 10025 # куда слать после проверки
Listen: 0.0.0.0:1025 # где ждем писем
ClamAddress: /var/run/clamav/clamd.sock
# где антивирус
Header: X-Virus-Scanned: ClamAV using ClamSMTP
# добавлять свой заголовок в письма
TempDirectory: /tmp
User: clamav # от кого запускать сервис
|
echo 'clamsmtpd_enable="YES"' >> /etc/rc.conf
/usr/local/etc/rc.d/clamsmtpd start
netstat -na | grep LIST
tcp4 0 0 *.1025 *.* LISTEN
|
Прикрутим это добро к Postfix
Попросим Postfix слушать еще один порт с почти пустыми ограничениями на прием. Сюда будет приходить почта от clamav. В mailloge логи по этому сервису будут проходить как postfix/clamav. И скажем что есть еще один транспорт для почты.
cd /usr/local/etc/postfix
|
master.cf
# ================================================
# Interface incoming post from clamav
127.0.0.1:10025 inet n - n - - smtpd
-o syslog_name=postfix/clamav
-o content_filter=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_end_of_data_restrictions=
-o smtpd_etrn_restrictions=
-o smtpd_data_restrictions=
-o smtpd_delay_reject=no
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks_style=host
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
# =====================================================
# Interface uotgoing post to clamav
clamsmtpd unix - - n - 16 smtp
-o smtp_send_xforward_command=yes
-o smtp_enforce_tls=no
# ====================================================================
| Теперь настроим куда сам Postfix должен слать почту
main.cf
content_filter = clamsmtpd:127.0.0.1:1025
receive_override_options = no_address_mappings
| Первой строкой сказали postfix'у что необходимо пересылать всю почту через сервис на 1025-ый порт. Вторая строчка говорит о том, чтобы postfix не делал никаких манипуляций с адресами до того, как они дойдут до content_filter. Если ее не будет, то, к примеру, bcc адресаты будут получать по 2 копии каждого письма.
/usr/local/etc/rc.d/postfix restart
|
проверяем, шлем почту, смотрим логи, в прошедшем письме должен появиься дополнительный заголовок (thunderbird вид-заголовки-все) X-Virus-Scanned ClamAV using ClamSMTP.
Работает, теперь надо послать какую-нить гадость.
пошлем EICAR строку.
X5O!
P%@AP
[4\PZX54
(P^)7CC)7}
$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
| Это одна строка, надеюсь этот сайт не попадет в распространители вируса ;)
после отсылки можно наблюдать в логах
Dec 11 18:24:10 mail postfix/smtp[2929]:
23D6D9CDF7: to=<mailadmin@tstdomain.ru>,
relay=127.0.0.1[127.0.0.1]:1025, delay=0.21,
delays=0.05/0.02/0.11/0.03, dsn=2.0.0, status=sent
(250 Virus Detected; Discarded Email)
Dec 11 18:24:10 mail clamsmtpd: 10000A:
from=test@tstdomain.ru, to=mailadmin@tstdomain.ru,
status=VIRUS:Eicar-Test-Signature
| письмо просто исчезает, не ответи ни привета. Настроим уведомления.
/usr/local/etc/clamsmtpd.conf
VirusAction: /usr/local/etc/clamsmtpd.virus.found
| /usr/local/etc/clamsmtpd.virus.found
#!/bin/sh
DOMAIN=tstdomain.ru
# Email address to send alerts to
ADMIN= mailadmin@tstdomain.ru
# formail should be in PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
LINE="-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
if [ X`echo $SENDER | egrep $DOMAIN` != "X" ];
then MAILTO=$SENDER,$ADMIN
else MAILTO=`echo "$RECIPIENTS" | egrep $DOMAIN | tr '\n' ','`
fi
(echo "Virus name: $VIRUS"
echo "Sender: $SENDER"
echo "Recipient(s): $RECIPIENTS"
echo
if [ "x$EMAIL" != "x" ] && [ -f $EMAIL ]
then
echo "Quarantined to: $EMAIL"
fi
) | cat -v | mail -s "$VIRUS found on mailserver" $MAILTO
| Не помню откуда спер этот офигительный своей простотой скриптик! Спасибо инету :).
Смысл вот в чем, не надо уведомлять отправителя вируса, как правило адреса там поддельные, и скорее всего отлупы от Вас пойдут невиновному адресату. Но если отправитель свой? И если мы ждем от кого - то письмо, а у этого бедняги завирусован комп? Пользователь бежит к Вам - админ где письмо ? ...
В этих строках производится проверка отправителя
if [ X`echo $SENDER | egrep $DOMAIN` != "X" ];
then MAILTO=$SENDER,$ADMIN
else MAILTO=`echo "$RECIPIENTS" | egrep $DOMAIN | tr '\n' ','`
fi
| и в зависимости от наш не наш домен шлется уведомление. Важно задать правильные переменные вначале. Если отправитель из нашего домена, то отлуп и отправителю и админу. Если шлют из чужого нам, то получателю мисьмо - что вот не прошло, работаем типа, он сам решит важный ли отправитель. в нашем случае для нескольких доменов, нужно просто расширить проверки:
VirusAction: /usr/local/etc/clamsmtpd.virus.found
| /usr/local/etc/clamsmtpd.virus.found
#!/bin/sh
DOMAIN=tstdomain.ru
DOMAIN1=abcdomain.ru
# Email address to send alerts to
ADMIN= mailadmin@tstdomain.ru
# formail should be in PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
LINE="-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
if [ X`echo $SENDER | egrep $DOMAIN` != "X" ];
then MAILTO=$SENDER,$ADMIN;
elif [ X`echo $SENDER | egrep $DOMAIN1` != "X" ];
then MAILTO=$SENDER,$ADMIN;
else MAILTO=`echo "$RECIPIENTS" | egrep $DOMAIN | tr '\n' ','`;
fi
(echo "Virus name: $VIRUS"
echo "Sender: $SENDER"
echo "Recipient(s): $RECIPIENTS"
echo
if [ "x$EMAIL" != "x" ] && [ -f $EMAIL ]
then
echo "Quarantined to: $EMAIL"
fi
) | cat -v | mail -s "$VIRUS found on mailserver" $MAILTO
| типа этого.
chown clamav:clamav /usr/local/etc/clamsmtpd.virus.found
chmod +x /usr/local/etc/clamsmtpd.virus.found
/usr/local/etc/rc.d/clamsmtpd restart
|
и проверяем.
Шаг 24 Lighttpd
Раз у нас есть почтовик, то прикрутим к нему web-морду.
Мне понравился roundcube, а веб сервер выбрал lighttpd - говорят простой и быстрый. Я не спец в вебе, не ругайте если что не так.
cd /usr/ports/www/lighttpd
make install && make clean
|
Из опций только OPENSSL
Чтобы работали php скрипты - roundcube, в lighttpd нужна поддержка fastcgi.
Насколько я понял можно это получить:
выбрав опцию spawn-fcgi - получим сервис слушающий на порту ... куда передаем на исполнение .php
выбрав опцию FPM при сборке PHP - получим сервис слушающий на порту ... куда передаем на исполнение .php
либо через сокет
Последнее мне показалось проще, так и сделаем. Поэтому при сборке lighttpd выбираем только SSL. Он понятно для чего нужен.
добавим в автозагрузку
echo 'lighttpd_enable="YES"' >> /etc/rc.conf
|
Соберем PHP Зачем7 - на нем написан roundcube иначе не заработает.
cd /usr/ports/lang/php5
make install && make clean
|
Из опций нужен только CGI
создадим необходимые киталоги
mkdir -p /usr/local/www/data/
chown www:www /usr/local/www
cd /usr/local/etc/lighttpd
|
lighttpd.conf
server.use-ipv6 = "disable"
server.bind = "192.168.0.100"
| думаю и так понятно что мы сделали. Условимся что мой сервер имеет этот адрес.
Задействуем модуль mod_fastcgi, именно через этот механизм будут исполняться .php скрипты
modules.conf
##
## FastCGI (mod_fastcgi)
##
include "conf.d/fastcgi.conf"
conf.d/fastcgi.conf
fastcgi.server = ( ".php" => ( "localhost" =>
( "socket" => "/tmp/fcgi.socket",
"min-procs" => 1,
"max-procs" => 4,
"bin-path" => "/usr/local/bin/php-cgi",
)
)
)
| fastcgi.server - куда отправлять fastcgi запросы.
"min-procs" и "max-procs" - минимальное и максимальное количество процессов php-cgi, которые и будут обрабатывать php-запросы. Значения 4, для применения в реальных условиях наверно маловато.
Создадим тестовый файлик
/usr/local/www/data/index.php
/usr/local/etc/rc.d/lighttpd restart
|
идем на http://192.168.0.100
Шаг 25 Roundcube
собственно само приложение...
Ставим
cd /usr/ports/mail/roundcube
make install
|
[x] DOCS Build and/or install documentation
[ ] GD Enable GD support (image conversion)
[x] LDAP Enable LDAP support (address book)
[ ] NSC Install network spellchecker
[x] PSPELL Enable PSpell support (internal spellcheck)
[ ] SSL Enable SSL support (imaps or google spellcheck)
----------— DB ---------------------------------
(*) MYSQL Use MySQL backend
( ) PGSQL Use PostgreSQL backend
( ) SQLITE Use SQLite backend
GD - не знаю что такое , LDAP - если адресная книга, на будущее поставил. NSC - за каждым словом в инет? PSPELL - проверка правописания, почему бы и нет. SSL - на imap будем коннектится как доверенные, зачем нам лишняя нагрузка. — DB -— - где будет личная база данных roundcube, ну раз уж MYSQL уже у нас есть..
должна появиться директория здесь /usr/local/www/data или здесь /usr/local/www/
нужно чтобы было так
/usr/local/www/roundcube
Заставим это работать.
cd /usr/local/etc/lighttpd
|
lighttpd.conf
server.document-root = "/usr/local/www/roundcube/"
|
/usr/local/etc/rc.d/lighttpd restart
|
идем на http://192.168.0.100/installer/index.php
здесь смотрим чего ему надо, и ставим нужное из php5-extensions
в консоли
cd /usr/ports/lang/php5-extensions/
make install && make clean
|
какие опции выбирать - смотрим что требует roundcube (FileInfo,OpenSSL,Mcrypt)
Кое что и отдельно доставить - Exif
cd /usr/ports/graphics/php5-exif
make install && make clean
|
Еще одна мелочь:
cd /usr/local/etc/
cp php.ini-production php.ini
|
php.ini
;date.timezone =
date.timezone = Europe/Moscow
|
/usr/local/etc/rc.d/lighttpd restart
|
Должны все красные надписи погаснуть...
next и далее уже сами
На последнем шаге
Mimetype to file extension mapping: NOT OK
с этим я не знаю как бороться. Там у roundcube свое что-то
ls /usr/local/www/roundcube/config/mimetypes.php
|
Где то здесь нужно создать в mysql базу
create database roundcubemail;
grant all on roundcubemail.* to 'roundcube'@'localhost';
grant all on roundcubemail.* to 'roundcube'@'127.0.0.1';
grant all on roundcubemail.* to 'roundcube'@'::1';
use mysql;
update user set password=password('password') where user='roundcube';
flush privileges;
\q
| и тут я наступил на свои же бережно разложеные грабли - отправка писем из roundcube.
я не понял, может ли roundcube создавать smtp сесии с tls или нет. В опциях сборки были только ¦+[ ] SSL Enable SSL support (imaps or google spellcheck)
вроде не к месту...
если пытаемся отправить на 587 порт - требует tls. настроили же :)
"smtpd_tls_security_level = encrypt"
объявление auth исчезло и не пропирает даже добавление хоста в mynetworks (main.cf)
ок, можно слать на порт 25. Но там мы не ждем своих клиентов, в данном случае веб сервер стоит там же где и postfix и машина являетя доверенной (mynetworks) можно вообще без авторизации. Вроде ничего криминального. Но, там в роундкубе можно настроить доп профиль с другим адресом отправителя, и ..... на 25 порту мы все примем! и даже если обратн адрес левый :( И как же настроенные ограничения для своих?
варианта выхода из ситуации 2 -
поднять еще один smtp сервис чисто для roundcube
или поправить рестрикш на порту 25- если доверенный ip то smtp auth
первый вариант мне показался проще,тем более что набор рестрикшенов уже готов..
ну, сказано - сделаем
сделаем копию с submission, но слушать будем только на 127.0.0.1 (это вариант с веб сервером там где и postfix) и уберем TLS, порт выбрал 250 и в сислог со своим префиксом пойдет...
master.cf
127.0.0.1:250 inet n - n - - smtpd
-o syslog_name=postfix/roundcube
-o smtpd_sasl_auth_enable=yes
-o smtpd_recipient_restrictions=$mua_recipient_restrictions
| smtpd_recipient_restrictions - даже не потребуется переписывать.
/usr/local/etc/rc.d/postfix restart
# netstat -na | grep LIST
tcp4 0 0 127.0.0.1.250 *.* LISTEN
|
пишем в роундкубе smtp 250, проверяем...
вуаля.
На последнем этапе нас просят..
After completing the installation and the final tests please remove the whole installer folder from the document root of the webserver or make sure that enable_installer option in config.inc.php is disabled.
enable_installer такой опции чет не нашел, тогда
rm -rf /usr/local/www/roundcube/installer
|
несколько плагинов уже идут в коплекте,
ls /usr/local/www/roundcube/plugins/
|
еще здесь куча плагинов к roundcube
http://trac.roundcube.net/wiki/Plugin_Repository
кое-что есть и в портах
cd /usr/ports/mail/roundcube-sieverules/
make install
|
cd /usr/local/www/roundcube/
|
Посмотреть что там в настройках, plugins/sieverules/config.inc.php
cp plugins/sieverules/config.inc.php{.dist,}
|
config/config.inc.php
$config['plugins'] = array(sieverules);
|
Шаг 26 Lighttpd SSL
Раз уж мы так старательно защищали smtp и imap то настроим и тут ssl.
cd /etc/ssl/
openssl req -new -x509 -keyout server.pem -out server.pem -days 3650 -nodes
|
Не обращаем внимание, что это я делаю уже 3-й раз....
Поправим конфиг lighttpd - перевесим его на порт 443, и добавим вирт хост.
cd /usr/local/ets/lighttpd/
|
lighttp.conf
server.port = 443
server.document-root = "/usr/local/www/roundcube/"
# где-то в середине
ssl.engine = "enable"
ssl.pemfile = "/etc/ssl/server.pem"
# и в самом конце добавим вирт хост
# IPv4 listening socket
$SERVER["socket"] == "192.168.0.100:80" {
server.document-root = "/usr/local/www/data/"
}
| Рестарт и смотрим как работает. Следующим шагом будет настройка редиректа с порта 80 на 443
Раскомментируем модуль отвечающий за нужную нам функциональность
modules.conf
server.modules = (
"mod_access",
# "mod_alias",
# "mod_auth",
# "mod_evasive",
"mod_redirect",
| и добавим кода сюда
lighttp.conf
# IPv4 listening socket
$SERVER["socket"] == "192.168.7.4:80" {
$HTTP["host"] =~ "(.*)" {
url.redirect = ( "^/(.*)" => "https://%1/$1" )
}
#server.document-root = "/usr/local/www/data/"
}
| Откуда все это добро? Отсюда https://wiki.archlinux.org/index.php/Lighttpd_(Русский)
Проверяем.
отчеты
# IPv4 listening socket
$SERVER["socket"] == "192.168.7.4:81" {
server.document-root = "/usr/local/www/data/"
}
vi /usr/local/www/data/index.html
/usr/ports/mail/mailgraph
make install
mailgraph_enable="YES"
MAILGRAPH CANNOT RUN: /var/log/maillog not readable by www
/usr/local/etc/rc.d/mailgraph: WARNING: failed precmd routine for mailgraph
chgrp www /var/log/maillog
/var/log/maillog root:www 640 7 * @T00 JC
/etc/newsyslog.conf
root@mail:~ # /etc/rc.d/newsyslog restart
Creating and/or trimming log files.
pflogsumm
http://www.sergeysl.ru/freebsd-postfix-mail-system/#more-176
Если Вы добрались сюда и вас все работает, и без ошибок в логах, то на этом можно остановиться. Настроенная конфигурация неплоха, но в процессе работы все равно что-то забываешь, ошибаешься и т. д. К примеру, уволился сотрудник, начальство требует алиас его почтового адреса, навсегда? - бред, ну ладно, на пол года, и что записи делать - удалить через пол года?
Я предлагаю сделать управление почтовыми ящиками/пользователями боле автоматическим. Для этого перелопатим базу mail и прибавим скриптик для автоматики. Если интересно - вперед.
........
Таблица domains
domain - список поддерживаемых нами доменов
Таблица users
user - адрес в формате user@domain
password - пароль
home - имя директории на файловой системе
quota - размер квоты (в гигабайтах, если в нужном месте стоит G)
acl_groups - группа, единственная (и acl и рассылки), пользователь будет входить только в одну группу. Имена групп будут жестко прописаны, для исключения ошибок. Я решил записывать группы без доменной части, так мне проще. На основе этого поля построим bcc maps и некоторые ограничения.
russian - описание, реальные имена пользователей
Таблица aliases
alias - дополнительный адрес
email - адрес реальный из users
exp_date - дата удаления
Смысл последнего - если пользователь увольняется, неплохо бы некоторое время поддерживать его почту, в качестве алиаса на адрес другого сотрудника. Но не вечно же, иначе алиасов становится очень много, в любом случае это быстро начинает мешать созданию новых пользователей. Чистить алиасы когда-то созданные? а некоторые могут быть нужны постоянно.. Переложим эту задачу на скрипт.
Таблица bcc
email - адрес, чьи письма копируем, жестко завязан на users
bcc_email - адрес кому, жестко завязан на users
Значения в эту таблицу будем заносить автоматом по признаку acl_groups. Типа менеджер - значит копия писем руководителю продажников. Можно добавлять другие записи вручную.
Таблица groups
groupname - групповой email-адрес
email - адрес, члена группы, жестко завязан на users.
Поля в этой таблице будут заполняться автоматом по признаку acl_groups. Можно добавлять свои группы вручную.
Создадим файлик, вместо моих тестовых доменов, можно уже вводить свои реальные.
я заливаю этот файлик по сети с linux, т.к. utf8.
Можно создать отдельного пользователя на free с utf8 или постирать все опции из my.cnf и этого файла.
Шаг Пользователь utf8
Создадим непривелигированного пользователя с нужной раскладкой.
/etc/login.conf
russian|Russian Users Accounts:\
#:charset=KOI8-R:\
#:lang=ru_RU.KOI8-R:\
:charset=UTF-8:\
:lang=ru_RU.UTF-8:\
:tc=default:
| подменены 2 строчки, теперь
и создаем пользователя, отвечая на кучу вопросов
Если коннектимя через putty, возможно нужно подправить в настройках 'tratnslations'
Шаг Создание новой базы
Ниже - весь скрипт создания базы, не оформлял как code - слишком много длинных строк.
ВНИМАНИЕ! обязательно править под себя - пароли, домены, адреса.
##############################################################
mk_mail_db_work.sql
# use this: mysql < mk_mail_db_work.sql
drop database if exists mail;
create database mail
DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
use mail;
create table domains(
domain VARCHAR(24) NOT NULL UNIQUE
);
create table users (
email VARCHAR(32) NOT NULL UNIQUE PRIMARY KEY,
home VARCHAR(16) NOT NULL UNIQUE,
password VARCHAR(64) NOT NULL,
quota INTEGER(10) UNSIGNED DEFAULT '0',
acl_groups ENUM('manager', 'hidden', 'public', 'buhgalteria', 'it', 'directora') NOT NULL,
russian VARCHAR(64) DEFAULT NULL
) ENGINE = InnoDB;
create table aliases (
alias VARCHAR(32) NOT NULL KEY,
email VARCHAR(32),
expire DATE NOT NULL DEFAULT '9999-12-31',
FOREIGN KEY (email) REFERENCES users(email) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;
create table bcc (
email VARCHAR(32),
bcc_email VARCHAR(32),
FOREIGN KEY (email) REFERENCES users(email) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (bcc_email) REFERENCES users(email) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (email, bcc_email)
) ENGINE = InnoDB;
create table groups (
groupname VARCHAR(32) ,
email VARCHAR(32),
FOREIGN KEY (email) REFERENCES users(email) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;
grant select on mail.* to 'mailreader'@'localhost';
grant select on mail.* to 'mailreader'@'127.0.0.1';
grant select on mail.* to 'mailreader'@'::1';
use mysql;
#update user set password=password('SecurePa$$') where user='mailreader';
flush privileges;
use mail;
# заполним первоначальными данными
insert into domains value ( 'tstdomain.ru', 'основной домен');
insert into domains value ( 'spb.tstdomain.ru', 'поддомен' );
insert into domains value ( 'abcdomain.ru', 'дополнительный домен' );
insert into domains value ( 'tstdomain.com', 'еще один домен' );
insert into users value ( 'allusermail@tstdomain.ru', 'allusermail', 'securepass', '10', 'hidden', 'вся проходящая почта');
insert into users value ( 'mailadmin@tstdomain.ru', 'mailadmin', 'securepass', '10', 'it', 'почта админа');
insert into users value ( 'manager@tstdomain.ru', 'manager', 'securepass', '2', 'manager', 'почта рядового менеджера');
insert into users value ( 'manager_ruk@tstdomain.ru', 'manager_ruk', 'securepass', '8', 'hidden', 'ящик для копий почты менеджеров');
insert into users value ( 'buh@tstdomain.ru', 'buh', 'securepass', '4', 'public', 'общий почтовый ящик бухгалтерии');
# bcc почтовые ящики должны быть hidden, это не именной ящик руководителя, а специальный, подключаемый отдельно.
# алиасы тоже заполним, такие адреса должны быть в почтовой системе
insert into aliases value ( 'abuse@tstdomain.ru', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'postmaster@tstdomain.ru', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'abuse@spb.tstdomain.ru.ru', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'postmaster@spb.tstdomain.ru', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'abuse@abcdomain.ru', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'postmaster@abcdomain.ru', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'abuse@tstdomain.com', 'mailadmin@tstdomain.ru', '9999-12-31' );
insert into aliases value ( 'postmaster@tstdomain.com', 'mailadmin@tstdomain.ru', '9999-12-31' );
# возможно еще нужно добавить webmaster....
##############################################################
таблицы bcc и groups будем заполнять автоматом.
Логика групп:
public - публичные ящики типа buh@tstdomain.ru, sales@tstdomain.ru - подключенные нескольким пользователям, не имеющие конкретного владельца. Это не групповые адреса, т.к. с одним ящиком на несколько человек можно видеть на какое входящее уже ответили,.. какое уже прочитано и в работе.. в отличие если бы это была группа.
hidden - скрытые ящики типа allusermail@tstdomain.ru, manager_ruk@tstdomain.ru - ящики для копий, с которых, на которые запрещено слать. эти ящики подключаются руководству, как дополнительные.
Заливаем все это добро
mysql < mk_mail_db_work.sql
|
Шаг Скрипт автоматизации
Используйте как пример, если кому не нравится как написан (кривой код и т. п.) нет проблем - пишите свое.
RUN.sh
##############################################################
##############################################################
#!/bin/sh
#_тут пароль от root из mysql
MYSQLPASS=
#_основной домен - допишем к acl_groups- получим группы рассылки.
DOMAIN=@tstdomain.ru
##_____задача: протестировать соединение с базой данных, если нет - завершаем скрипт
##_____как индикатор - спрашиваем "постоянную" запись из базы
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT email=' ' FROM users WHERE email='mailadmin@tstdomain.ru'"` ]
then
echo "test connection to database success, database online"
else
echo "test connection to database error, exiting"
exit
fi
###################################################################
##_____задача: удалить почтовые каталоги удаленных пользователей
##_____предполагаем что кроме пользовательских почтовых каталогов в папке
##_____ /MAIL/ мусора не будет. Для теста еще проверим наличие знаковых каталогов внутри ...
##_____________________________________________clear homedir deleted users
clearhomedir () {
for I in `ls /MAIL/`
do
if [ -d /MAIL/${I} ] && [ -d /MAIL/${I}/Maildir/cur ] && [ -d /MAIL/${I}/Maildir/new ]
then
echo "test folder /MAIL/${I} success - this is maildir"
II=`echo "'"${I}"'"`
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT home=' ' FROM users WHERE home=
${II}"` ]
then
:
echo "user homedir ${I} present in database, user live"
else
echo "user homedir ${I} not found in database, do remove homedir"
echo "rm -rf /MAIL/${I}"
#rm -rf /MAIL/${I}
fi
else
:
#echo "${I} is not maildir?"
fi
done
}
###################################################################
##_____задача: удалить просроченные алиасы
##________________________________________________crear_aliases
clearaliases () {
CURDATE=`date +%Y-%m-%d`
EXPIRE=`echo "'"${CURDATE}"'"`
echo ${EXPIRE}
#mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="DELETE FROM aliases WHERE expire < $EXPIRE"
}
###################################################################
##_____задача: найти незаполненные acl_groups в таблице users
##_____согласно логике такого быть не должно
##___________________________________check_for_empty_acl_groups
checkemptyacl () {
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT home='' FROM users WHERE acl_groups=0"` ]
then echo "acl_groups 0 not present in aclgroups"
else
echo "WARNING! in acl_groups present 0 value!"
exit
fi
}
##################################################################
##_____задача: проверить совпадение адресов пользователей с адресами alias и групповыми адресами
##_____совпадение с алиасами еще может быть нормальным, а вот с группой - уже не совсем правильно
##___________________________________check if user email present in aliases or groupname
checkuseralias () {
for I in `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT email FROM users"`
do
II=`echo "'"${I}"'"`
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT alias=' ' FROM aliases WHERE alias=${II
}"` ]
then
echo "WARNING! value ${II} from users present in aliases!"
#else
# echo "OK value ${II} from users not present in aliases!"
fi
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT groupname=' ' FROM groups WHERE groupna
me=${II}"` ]
then
echo "WARNING! value ${II} from users present in groups!"
#else
# echo "OK value ${II} from users present in groups!"
fi
done
}
###################################################################
##_____задача: проверить совпадение alias-ов с групповыми адресами
##_____если есть алиас с адресом как у группы, -группа не будет работать.
##___________________________________check if alias present in groupname
checkaliasgroup () {
for I in `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT alias FROM aliases"`
do
II=`echo "'"${I}"'"`
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT groupname=' ' FROM groups WHERE groupna
me=${II}"` ]
then
echo "WARNING! value ${II} from aliases found in groups!"
#else
# echo "OK value ${II} from aliases not found in group!"
fi
done
}
###################################################################
##_____задача: выбрать acl группы, кроме скрытой (hidden) и публичной (public)
##_____для них - получить членов - обновить таблицу groups
##_____и навоять новые файлы ограничений
###____________________________________________processing_group
groupprocess () {
## get values acl_groups, not public, not hidden
for GR in `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT distinct acl_groups FROM users WHERE (acl_
groups<>'hidden' && acl_groups<>'public')"`
do
echo "processing acl-group ${GR}"
GROUP=`echo "'"${GR}"'"`
DOMGROUP=`echo "'"${GR}${DOMAIN}"'"`
echo ${GROUP}
echo ${DOMGROUP}
##_____________________clear aliases for this group
mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="DELETE FROM groups where groupname=${DOMGROUP}"
##_____________________poluchim chlenov gruppi
for I in `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT email FROM users WHERE acl_groups=$
{GROUP}"`
do
#echo " user getting $I"
USEREMAIL=`echo "'"${I}"'"`
#echo " ${DOMGROUP} ${USEREMAIL}"
mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="INSERT INTO groups value ( ${DOMGROUP}, ${US
EREMAIL} )"
done
##___________add to restrictions
echo "${GR}${DOMAIN} 550 User unknown in virtual mailbox table." >> /tmp/rej_group_recipient.hash
done
# maybe need add custom restrictions
# cat custom_restrictions >> /tmp/rej_group_recipient.hash
mv /tmp/rej_group_recipient.hash /usr/local/etc/postfix/restrictions/rej_group_recipient.hash && postmap /usr/local/etc/postfix/restrictions/rej_group_
recipient.hash
}
###################################################################
##_____задача: навоять файлы ограничений по признаку acl_group=hidden из базы
##___________________create restrictions for hidden address
restrictions () {
for I in `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT email FROM users WHERE acl_groups='hidden'"
`
do
echo "${I} 550 User unknown in virtual mailbox table." >> /tmp/rej_int_recipient.hash
echo "${I} 554 Please dont use this sender email." >> /tmp/rej_int_sender.hash
done
mv /tmp/rej_int_recipient.hash /usr/local/etc/postfix/restrictions/rej_int_recipient.hash && \
postmap /usr/local/etc/postfix/restrictions/rej_int_recipient.hash
mv /tmp/rej_int_sender.hash /usr/local/etc/postfix/restrictions/rej_int_sender.hash && \
postmap /usr/local/etc/postfix/restrictions/rej_int_sender.hash
}
###################################################################
##_____задача: обновить записи таблицы bcc, согласно заданным acl_groups и bcc_adress
##_____параметры этой функции передадим ниже
##____________________________update bcc table
bcc () {
GROUP=`echo "'"${1}"'"`
EMAIL=`echo "'"${2}"'"`
echo ${EMAIL}
##____________________________clear rows for this bcc_email
mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="DELETE FROM bcc WHERE bcc_email=${EMAIL}"
##___________________________get users email with this acl_group
for I in `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT email FROM users WHERE acl_groups=${GROUP}"
`
do
USEREMAIL=`echo "'"${I}"'"`
##___________________insert new rows with this value
mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="INSERT INTO bcc value (${USEREMAIL}, ${EMAIL})"
done
}
############################################
#### body programm ####
###########################################
##_____задача: протестировать соединение с базой данных, если нет - завершаем скрипт
##_____как индикатор - спрашиваем "постоянную" запись из базы
if [ `mysql -u root --password=$MYSQLPASS --database=mail --skip-column-names --batch --execute="SELECT email=' ' FROM users WHERE email='mailadmin@tstdomain.ru'"` ]
then
echo "test connection to database success, database online"
else
echo "test connection to database error, exiting"
exit
fi
##_____запускаем по очереди все наши цели
clearhomedir
clearaliases
checkemptyacl
groupprocess
restrictions
checkuseralias
checkaliasgroup
##______________________call function with value 'acl-groups' 'bcc_email' for this acl-groups
bcc manager manager_ruk@tstdomain.ru
##______________________reload postfix, for read new restrictions
/usr/local/etc/rc.d/postfix reload
##############################################################
##############################################################
Как вариант использования - запихнуть в cron.
Или отдать тому непривилегированному пользователю с utf8 и приделать setuid. Важно проверить работу всего этого дела у себя, особенно кусок чистящий maildir пользователей.
размещено: 2014-12-10,
последнее обновление: 2015-01-26,
автор: KontraBass
|
|
|
|
2014-07-27, lissyara
gmirror
Удалённое создание софтверного зеркала средствами gmirror, на диске разбитом с использованием gpart. Использование меток дисков для монтирования разделов.
2013-08-20, zentarim
Scan+Print server FreeBSD 9
Настройка сервера печати и сервера сканирования под управлением операционной системы FreebSD 9 для МФУ Canon PIXMA MP540
|