Мы — долго запрягаем, быстро ездим, и сильно тормозим.

FreeBSD
  настройка
  подсчёт трафика
  программы
  почтовые системы
  FreeBSD Mail Howto
  exim & dovecot
  exim & courier-imap
  squirrelmail
  exim + saslauthd + courier-imap
  postfix -> exim
  sendmail -> exim
  imapsync
  Postfix + LDAP
  maildrop & postfix
  DSPAM
  Exim + LDAP
  ISPmanager
  Backup MX
  exim + exchange
  exim + dovecot + win2003 AD
  RoundCube
  qmail-ldap + AD
  spamooborona
  exim&dovecot + fetchmail + SSL
  Postfix + DBMail
  Mailgraph
  smfsav
  Exim+PgSQL
  Postfix + Dovecot + Clamav + SpamAssasin + LDAP vs MYSQL
  Simplemail Admin
  MTA qmail full install
  OpenLDAP адресная книга
  POSTFIX Статистики
  Backup MX (exim)
  Exim + dovecot + PgSQL + web
  Exim+dovecot2+dspam
  Возможности Dovecot 2
  Dovecot2 configfiles RUS
  Почтовый сервер по шагам ч.1
  Почтовый сервер по шагам ч.2
  Почтовый сервер по шагам ч.3
  Шелезяки
  Мелочи
  Файловая система
  WWW
  Security
  system
  Games Servers
  X11
  Programming
Очумелые Ручки
OpenBSD
Cisco


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. Он понятно для чего нужен.
              [X]  SSL

добавим в автозагрузку
echo 'lighttpd_enable="YES"' >> /etc/rc.conf

Соберем PHP Зачем7 - на нем написан roundcube иначе не заработает.
cd /usr/ports/lang/php5
make install && make clean

Из опций нужен только CGI
              [X] 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
<?php
phpinfo();
?>

/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 строчки, теперь
cap_mkdb /etc/login.conf

и создаем пользователя, отвечая на кучу вопросов
adduser -L russian

Если коннектимя через 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

оценить статью:


Хостинг HOST-FOOD

2014-07-27, lissyara
gmirror

Удалённое создание софтверного зеркала средствами gmirror, на диске разбитом с использованием gpart. Использование меток дисков для монтирования разделов.
2013-08-20, zentarim
Scan+Print server FreeBSD 9

Настройка сервера печати и сервера сканирования под управлением операционной системы FreebSD 9 для МФУ Canon PIXMA MP540
подписка

    вверх      
Статистика сайта
Сейчас на сайте находится: 19 чел.
За последние 30 мин было: 92 человек
За сегодня было
7036 показов,
999 уникальных IP
 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.2347 секунд
Из них PHP: 68%; SQL: 32%; Число SQL-запросов: 75 шт.
Исходный размер: 150482; Сжатая: 27780