На работе решил заточить почтовый сервер (на замену старому). Что требуется от сервера? Авторизация как по MySQL так и по LDAP. По хорошему, надо NTLM, но только на внутреннюю сеть. Также желательно нацепить антивирус, антиспам, квотирование, и т. п. Выбор пал на связку Dovecot 2 + Postfix (SASL dovecot 2).
В качестве операционной системы выбрал FreeBSD 10, так как считаю, что в корпоративном сегменты это лучший выбор из бесплатного.
Почему не Debian и производные? Ну не люблю я debian. Допиливание того, что «из коробки», пляски с репозиториями, попытки совместить несовместимое, неинтуитивные решения некоторых проблем... Ну не лежит у меня верхняя часть туловища к нему.
Почему не rpm? Честно, мне нравится OpenSUSE. Но как настольная операционка. В серверной части она не отстаёт только при 1 условии: отсутствие yast. То есть все плюсы этой операционки отсекаются в серверном решении. А это значит, что разобраться в моих конфигах будет сложнее на порядок.
FreeBSD. По сути, не нуждается в обновлениях. Не так уж то и много неявных решений. То есть если делать по уму, то разобраться сможет любо знакомый с этой системой. На мой взгляд самое то.
Начнём.
Настройка FreeBSD
На тему установки литературы море. Делаем всё штатно. При выборе параметров установки не выбрал ничего. Всё, что нужно настрою после. В обязательно указываем SSHD. Остальное на вкус. Добавил пользователя. В дополнительных группах указал wheel, чтобы удачно выполнять sudo. Ребут. Заходим под рутом (я зашёл по ssh, а значит сначала под своей учётной записи, а потом «su»)
Займёмся портами.
# portsnap fetch
# portsnap extract
Эти команды будут выполняться около 5 минут (зависит от скорости тырнета). Первая команда скачивает коллекцию портов, а вторая эту коллекцию распаковывает. Так, как коллекции у меня на данный момент нет, то необходима именно распаковка.
Дальше нужно обновить исходные коды:
# svnlite co https://svn.freebsd.org/base/head /usr/src
Ждёмс...
После получения исходных кодов можно обновлять операционку:
# freebsd-update fetch
# freebsd-update install
Теперь перед перезагрузкой я бы посоветовал установить необходимые программы. А именно: sudo, portupgrade, nano, subversion. Я косервативен. Плюс люблю всё контролировать. Поэтому make =))
- nano
# cd /usr/ports/editors/nano
# make config-recursive
# make config-recursive
2 раз бывает необходим, если вы правили зависимости у зависимых пакетов. Советую поначалу ставить всё по умолчанию. Если вы, конечно, не знаете, что делаете.# make install clean
# rehash
Сразу же правлю# nano /root/.cshrc
…
#setenv EDITOR vi
setenv EDITOR nano
…
Не привык я в своё время к vi =(. - sudo
# cd /usr/ports/security/sudo
# make config-recursive
# make config-recursive
# make install clean
# rehash
Правлю# visudo
Закомментировал строчку#root ALL=(ALL) ALL
Эта строчка разрешает запуск sudo всем пользователям
Раскомментировал%wheel ALL=(ALL) ALL
Эта строчка разрешает запуск sudo только пользователям группы wheel (а мы как раз и в ней)
Добавил строчкуDefault timestamp_timeout=30
Эта магичаская строчка добавит возможность не вводить пароль в течение 30 минут простоя. Кстати! Обратил внимание на строчку#Defaults targetpw
Эта строчка требует ввод пароль от РУТА! Если закомментирована запуск sudo требует пароль пользователя. - portupgrade. Этот пакет поможет следить за обновлениями.
# cd /usr/ports/ports-mgmt/portupgrade
# make config-recursive
# make config-recursive
# make install clean
# rehash - subversion. Этот пакет поможет обновлять исходные коды системы.
# cd /usr/ports/devel/portupgrade
# make config-recursive
# make config-recursive
# make install clean
# rehash - Подтянул UTF-8 на русском:
# nano /etc/login.conf
…
russian|Russian Users Accounts:\
:charset=UTF-8:\
:lang=ru_RU.UTF-8:\
:tc=default:
….
# cap_mkdb /etc/login.conf - Добавил себе русский язык:
# pw usermod -n croatoan -L russian
- И напоследок создал скрипт обновления:
# cat << DELIMITER > /etc/update.sh
#!/bin/sh
cd /usr/src
make update SVN_UPDATE=yes
freebsd-update fetch
freebsd-update install
portsnap fetch
portsnap update
portupgrade -aR
DELIMITER
# chmod +x /usr/update.sh
Всё. Перезагружаемся (Перезагрузка может повиснуть.Долго висит строчка про синхонизацию буфера. Ребутнул вручную). После загрузки испытал скрипт. Шик =))
Подготовка дополнительного диска.
Захожу по ssh. У мнея на root очень сложный пароль — задалбываюсь набирать. Регламент тудыть его... Поэтому
# sudo -s
Ищу диски
# gpart list
У меня полуаппаратный рэйд, который я уже поднял на уровне контроллера. FreeBSD прекрасно с ним работает, а значит, мне не придётся колошматить mdadm =). Вижу, что есть raid/r0 с разметками и неразмеченный raid/r1. Challenge accepted. ВНИМАНИЕ! Дальнейшие действия могут навредить данным, вашей нервной системе и существенно навредить здоровью (нервы, побои). Очень много думать над вводом.
# gpart create -s GPT /raid/r1
# gpart add -t freebsd-ufs /raid/r1
# gpart list
Вот теперь есть и раздел, и область. Разметил
# newfs -U /dev/raid/r1p1
Дальше. Создал папку
# mkdir /data
И примонтировал диск тудыть:
# mount /data /dev/raid/r1p1
Добавил в автомонтирование:
# nano /etc/fstab
…
/dev/raid/r1p1 /data ufs rw 1 1
MySQL
Тут ничего сложного.
# cd /usr/ports/databases/mysql56-server
# make config-recursive
# make config-recursive
# make install clean
# rehash
Добавил в сервисы:
# sysrc mysql_enable=YES
Запустил
# service mysql-server start
Настроил безопасность
# mysql_secure_installation
Задал пароль root, запретил ему удалённый доступ, удалил тестовую базу и прочее... Добавил себя =))
# mysql -u root -p
<password>
mysql> Grant all privileges on *.* to <myname>@localhost identified by '<mypass>' with grant option;
mysql> Grant all privileges on *.* to <myname>@'192.168.0.%' identified by '<mypass>' with grant option;
mysql> flush privileges;
mysql> quit;
Разрешил себе входить с самого сервера и с компов сети. (Замени <myname>, <mypass> и сеть на свои)
Всё.
Dovecot 2
Пришло время почтового сервера. Покажу только основные настройки. Дальше — гугл в помощь.
# cd /usr/ports/mail/dovecot2
# make config-recursive
Выбираем поддержку LDAP и MySQL.
# make config-recursive
# make install clean
# rehash
Конфиги по умолчанию (или примерные конфиги) в рабочую папку.
# cp -R /usr/local/etc/dovecot/example-config/* /usr/local/etc/dovecot/
Добавил запуск службы
# sysrc dovecot_enable=YES
Пока не запускаю.
Нужно добавить учётную запись для почтового сервиса.
Добавил группу с заранее заданным ID
# pw groupadd vmail -g 5000
Добавил пользователя с запретом входа с заранее заданным id
# pw useradd vmail -u 5000 -g vmail -s /usr/sbin/nologin -d /nonexistent -c «Virtual Mail User»
Создал папку для хранения почты и привязал её к новому пользователю
# mkdir /data/mail
# chown vmail:vmail /data/mail
Дальше правлю конфиги.
# nano /usr/local/etc/dovecot/dovecot.conf
…
protocols = imap pop3
…
listen = *
…
#!include_try local.conf
# nano /usr/local/etc/dovecot/conf.d/10-auth.conf
Разрешил прямую передачу пароля
disable_plaintext_auth = no
Разрешённые символы в поле логина
auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
Все логины в нижнем регистре
auth_username_format = %Lu
Механизмы авторизации
auth_mechanisms = plain login
Вчключил методы входа. Сначала LDAP а потом, если не нашёл, то MySQL
!include auth-ldap.conf.ext
!include auth-sql.conf.ext
# nano /usr/local/etc/dovecot/conf.d/10-logging.conf
На своё усмотрение. При тесте желательно включить все логи. Потом не забудь выключить!
# nano /usr/local/etc/dovecot/conf.d/10-mail.conf
Где будет физически лежать почта
mail_location = maildir:/data/mail/%d/%n
Жёстко привязал доступ к созданной учётной записи
mail_uid = 5000
mail_gid = 5000
# nano /usr/local/etc/dovecot/conf.d/10-ssl.conf
На время выключаю SSL
ssl = no
#ssl_cert = </etc/ssl/certs/dovecot.pem
#ssl_key = </etc/ssl/private/dovecot.pem
# nano /usr/local/etc/dovecot/conf.d/15-mailboxes.conf
Автосоздание и подвязка некоторых папок: Отправленные, Архив, Спам, Корзина и т.п.
auto = subscribe
...
special_use = \Archive \Drafts \Junk \Sent \Trash
...
mailbox Archive {
special_use = \Archive
}
Авторизация LDAP
Дальше идёт самое вкусное =))) Настройка авторизации из LDAP. Поехали.
# nano /usr/local/etc/dovecot/dovecot-ldap.conf.ext
Так как у меня ActiveDirectory на MS Server 2008 R2 пишу
hosts = <ip>:3268
Замени <ip> на свой
Под кем будем заходить? У меня для этого создана учётная запись с минимальными правами =)
dn = <User>@<Domain>
dnpass = <Pass>
Замени на <User>, <Domain> и <Pass> свои.
Так как у меня AD, то
tls = no
…
auth_bind = yes
…
ldap_version = 3
Где искать пользователей??? На примере домена sam.dom
base = dc=sam,dc=dom
Сразу замечу, что имя ПОЧТОВОГО домена может не совпадать с именем КОНТРОЛЛЕРА домена.
Как искать?
deref = searching
scope = subtree
Схема пользователей
user_filter = (mail=%u)
pass_filter = (mail=%u)
И последний штрих:
default_pass_scheme = CRYPT
Авторизация MySQL
Вроде всё.
А теперь весёлость. Создаю базу. По привычке все ключевые моменты на представлениях. Если будет интересно, объясню что, как и зачем. Итак.
База:
CREATE DATABASE IF NOT EXISTS `mail`;
USE `mail`;
Таблица доменов. Мало ли сколько их будет...
CREATE TABLE IF NOT EXISTS `Domains` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Domain` varchar(128) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `UK_Domains_Domain` (`Domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Таблица логинов пользователей:
CREATE TABLE IF NOT EXISTS `Logins` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ID_Domain` int(10) unsigned NOT NULL,
`Login` varchar(128) NOT NULL,
`Password` varchar(256) NOT NULL,
`Name` varchar(512) DEFAULT NULL,
`Quota` int(11) DEFAULT NULL,
`Home` varchar(512) DEFAULT NULL,
`EditDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`),
UNIQUE KEY `UK_Logins_Login` (`ID_Domain`,`Login`),
CONSTRAINT `FK_Logins_IDDomain` FOREIGN KEY (`ID_Domain`) REFERENCES `Domains` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Таблица оснований редактирования записей:
CREATE TABLE IF NOT EXISTS `Reasons` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Reason` varchar(255) NOT NULL,
`IsActive` bit(1) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `UK_Reason_Reason` (`Reason`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Таблица активности учётных записей:
CREATE TABLE IF NOT EXISTS `Activity` (
`ID` int(10) NOT NULL AUTO_INCREMENT,
`ID_Login` int(10) unsigned NOT NULL,
`Date` date NOT NULL,
`ID_Reason` int(11) unsigned NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `UK_Activity_IDLogin_PeriodStart` (`ID_Login`,`Date`),
KEY `FK_Activity_IDReason` (`ID_Reason`),
CONSTRAINT `FK_Activity_IDLogin` FOREIGN KEY (`ID_Login`) REFERENCES `Logins` (`ID`),
CONSTRAINT `FK_Activity_IDReason` FOREIGN KEY (`ID_Reason`) REFERENCES `Reason` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Теперь нужно прикрепить проверку активности записей:
CREATE FUNCTION `UF_GetActivity`(`@ID_Login` INT) RETURNS bit(1)
BEGIN
Select r.`IsActive`
From `Activity` a
Join `Reasons` r on
a.`ID_Reason` = r.`ID`
Where
a.`Date` < CurDate() and
a.`ID_Login` = `@ID_Login`
Order by a.`Date` Desc
Limit 1
Into @Res;
Return @Res;
END;
Создал представления для проверки данных почтарём:
CREATE VIEW `V_Logins` AS select `l`.`ID` AS `id`,concat(`l`.`Login`,'@',`d`.`Domain`) AS `user`,`l`.`Password` AS `password`,`l`.`Login` AS `username`,`d`.`Domain` AS `domain`,ifnull(`l`.`Quota`,100) AS `quota`,ifnull(`l`.`Home`,concat('/data/mail/',`d`.`Domain`,'/',`l`.`Login`,'/')) AS `home`,ifnull(`UF_GetActivity`(`l`.`ID`),0) AS `isactive` from (`Domains` `d` join `Logins` `l` on((`l`.`ID_Domain` = `d`.`ID`)));
CREATE VIEW `V_Iterate` AS select `V_Logins`.`user` AS `User` from `V_Logins` where (`V_Logins`.`isactive` = 1);
CREATE VIEW `V_Pass` AS select `V_Logins`.`user` AS `user`,`V_Logins`.`username` AS `username`,`V_Logins`.`domain` AS `domain`,`V_Logins`.`password` AS `password` from `V_Logins` where (`V_Logins`.`isactive` = 1);
CREATE VIEW `V_User` AS select `V_Logins`.`user` AS `user`,`V_Logins`.`username` AS `username`,`V_Logins`.`domain` AS `domain`,`V_Logins`.`home` AS `home` from `V_Logins` where (`V_Logins`.`isactive` = 1);
Для удобства пару триггеров:
CREATE TRIGGER `tr_Logins_bi` BEFORE INSERT ON `Logins` FOR EACH ROW BEGIN
Set New.`Password` = SHA2(New.`Password`, 512);
END;
CREATE TRIGGER `tr_Logins_bu` BEFORE UPDATE ON `Logins` FOR EACH ROW BEGIN
if Old.`Password` != New.`Password` then
Set New.`Password` = SHA2(New.`Password`, 512);
end if;
END;
Вуаля. То есть нужно напрямую передавать пароль. За шифрование отвечает база. Осталось научить Dovecot принимать данные.
# nano /usr/local/etc/dovecot/dovecot-sql.conf.ext
Подключение к базе:
…
driver = mysql
…
connect = host=localhost dbname=mail user=<user> password=<pass>
Возможно, кто-нибудь заметил, что я использую схему шифрования паролей SHA2. Добавлю в схему совместимость:
…
default_pass_scheme = SHA512
Запросы:
…
password_query = Select user, username, domain, password From V_Pass where user = '%u'
…
user_query = Select user, username, domain, home From V_User where user = '%u'
…
iterate_query = Select user From V_Iterate
Вроде, всё.
Проверка
Проверить очень просто. Telnet. На любой машине ставим telnet и проверяем:
telnet <ip> pop3
> user <username>@<domain>
> pass <password>
Проверить как на mysql так и на ldap. У меня всё завелось... Если не получилось — читать логи.
Postfix.
Всё как обычно
# cd /usr/ports/mail/postfix
# make config-recursive
Выбрать Dovecot2 SASL authentification method
# make config-recursive
# make install clean
# rehash
При установке система спроситпро активацию в папке бла-бла-бла. Не имею возражений.
Дальше САМОЕ сложное — подружить Postfix и Dovecot. Для начала отключаю поддержку sendmail:
# cat << DELIMITER » /etc/rc.conf
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
DELIMITER
# cat << DELIMITER > /etc/periodic.conf
heredoc> daily_clean_hoststat_enable="NO"
heredoc> daily_status_mail_rejects_enable="NO"
heredoc> daily_status_include_submit_mailq="NO"
heredoc> daily_submit_queuerun="NO"
DELIMITER
Заргузка:
# sysrc postfix_enable=YES
ПОНЕСЛАСЬ!!!!!
Правлю конфиги dovecot:
# nano /usr/local/etc/dovecot/conf.d/10-master.conf
…
service auth {
...
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
…
Правлю конфиги postfix:
# nano /usr/local/etc/postfix/main.cf
Добавил
…
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
Перезаргузка...
# reboot
Проверка под почтовым клиентом. Полёт нормальный.
Итого: за рабочий день полностью установлен и настроен почтовый сервер организации.
Статья будет эволюционировать. Шлифую узкие места =)
Приурочено к дню системного администратора.
Любая копипаста с позволения автора.