Необходимые компоненты:
Но обо всем по порядку
В примере будем использовать следующие «переменные»:
Допустим у нас есть приобретенные 2-3 доменных имени, для которых мы планируем создать почту (ради одного доменного имени задача сильно проще, но лучше иметь возможность расширения)
Во-первых, нужен собственный сервер в публичной сети ( VPS / VDS )
Во-вторых, обязательно должна быть обратная PTR-запись, иначе ваши письма никуда не уйдут
Первое - у нашего облачного провайдера делаем обратную PTR-запись - 40.40.40.40-in-arpa указывающую на наш mail.firstdomain.com
Далее поднимаем и устанавливаем BIND:
yum install bind bind-chroot bind-utils
Настраиваем конфиг (краткая выжимка из обязательных параметров, остальные параметры не трогаем):
/var/named/chroot/etc/named.conf
options {
listen-on port 53 { any; };
listen-on-v6 port 53 { ::; };
allow-query { any; };
recursion no;
version "DNS Server";
dnssec-enable yes;
dnssec-validation yes;
};
...
zone "firstdomain.com" IN {
type master;
file "firstdomain.com.zone";
allow-update { none; };
};
zone "secondomain.org" IN {
type master;
file "secondomain.org.zone";
allow-update { none; };
};
zone "thirdomain.ru" IN {
type master;
file "thirdomain.ru.zone";
allow-update { none; };
};
...
Теперь опишем файлы зон:
/var/named/firstdomain.com.zone
$TTL 86400
@ IN SOA ns1.firstdomain.com. mail.firstdomain.com. (
1 ;Serial (need to manual inc with every editting zone file for transfer zone to slave)
3600 ;Refresh
1800 ;Retry
604800 ;Expire
86400 ;Minimum TTL
)
@ IN NS ns1.firstdomain.com.
@ IN NS ns2.firstdomain.com.
@ IN A 40.40.40.40
www IN A 40.40.40.40
mail IN A 40.40.40.40
patfixadm IN A 40.40.40.40
@ IN MX 10 mail.firstdomain.com.
ns1 IN A 40.40.40.40
ns2 IN A 40.40.40.40
/var/named/secondomain.org.zone
(содержание /var/named/thirdomain.ru.zone
аналогичное)
$TTL 86400
@ IN SOA ns1.firstdomain.com. mail.firstdomain.com. (
1 ;Serial (need to manual inc with every editting zone file for transfer zone to slave)
3600 ;Refresh
1800 ;Retry
604800 ;Expire
86400 ;Minimum TTL
)
@ IN NS ns1.firstdomain.com.
@ IN NS ns2.firstdomain.com.
@ IN A 40.40.40.40
www IN A 40.40.40.40
@ IN MX 10 mail.firstdomain.com.
Первичная настройка зон завершена, позднее впишем по две TXT-записи.
На старт:
systemctl enable named-chroot --now
Забегая вперед, уточню. Ставить будем в связке nginx+apache+php+mariadb, чтобы удовлетворить требования прикладных систем.
yum install nginx
yum install mariadb
yum install MariaDB-Galera-server MariaDB-client MariaDB-common MariaDB-shared
yum install centos-sclo-rh centos-sclo-sclo
yum install httpd24-httpd httpd24-httpd-tools httpd24-libnghttp2 httpd24-runtime
yum install rh-php73-php rh-php73-php-cli rh-php73-php-common rh-php73-php-fpm rh-php73-php-gd rh-php73-php-intl rh-php73-php-json rh-php73-php-mbstring rh-php73-php-mysqlnd rh-php73-php-pdo rh-php73-php-xml rh-php73-php-xmlrpc rh-php73-php-zip rh-php73-php-pear rh-php73-php-pgsql
Итак, необходимые версии пакетов установлены, обратите внимание - PHP 7.3 (поддержка завершена, рекомендовано к установке от 8.0) в Centos 7 (завершен срок жизни ОС) устанавливается из отдельных репозиториев rh. Это связано с тем, что ни в base, ни в epel для Centos 7 уже не поставляется PHP свежее, чем версия 4.5. Тоже самое касается и Apache. Устанавливаем версию 2.4 из пакета rh.
Побежали настраивать WEB-составляющую нашего комбайна («монстра»).
Этот сервис мы не будем «выставлять наружу», будем слушать один порт на 127.0.0.1 (localhost).
В SELinux для Apache по мимо стандартных tcp/80 и tcp/443 уже предопределены дополнительные порты, поэтому необходимости что-то добавлять нет. Просто возьмем уже имеющийся в списке tcp/8008 (не заменяйте весь конфиг Apache целиком, только ниже приведенные параметры).
/opt/rh/httpd24/root/etc/httpd/conf/httpd.conf
Listen 127.0.0.1:8008
ServerSignature Off
ServerTokens Prod
IncludeOptional conf.d/*.conf
IncludeOptional sites-enabled/*.conf
Создаем папку:
mkdir /opt/rh/httpd24/root/etc/httpd/sites-enabled
В этой папке и будут конфигурации наших WEB-ресурсов.
Далее настроим реверс-прокси, но пока нас интересует 2 виртуальных хоста - это mail.firstdomain.com и postfixadm.firstdomain.com. Создадим их в папке sites-enabled.
/opt/rh/httpd24/root/etc/httpd/sites-enabled/mail.conf
<VirtualHost *:8008>
ServerName mail.firsdomain.com
ServerAlias mail.firsdomain.com
SetEnvIf X-Forwarded-Proto https HTTPS=on
DocumentRoot /var/www/mail/
<Directory "/var/www/mail">
AllowOverride None
Require all granted
</Directory>
DirectoryIndex index.php
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@firstdomain.com"
php_admin_value session.save_path /var/log/httpd24/
ErrorLog /var/log/nginx/apache-mail-error.log
CustomLog /var/log/nginx/apache-mail-access.log combined
</VirtualHost>
/opt/rh/httpd24/root/etc/httpd/sites-enabled/padmin.conf
<VirtualHost *:8008>
ServerName postfixadm.firsdomain.com
ServerAlias postfixadm.firsdomain.com
SetEnvIf X-Forwarded-Proto https HTTPS=on
DocumentRoot /var/www/padmin/
<Directory "/var/www/padmin">
AllowOverride None
Require all granted
</Directory>
DirectoryIndex index.php
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@firstdomain.com"
php_admin_value session.save_path /var/log/httpd24/
ErrorLog /var/log/nginx/apache-padmin-error.log
CustomLog /var/log/nginx/apache-padmin-access.log combined
</VirtualHost>
Соответственно создадим эти папки:
mkdir /var/www/mail
mkdir /var/www/padmin
Запускаем Apache и проверяем, если все ок, добавляем в автозагрузку:
systemctl start httpd
systemctl enable httpd
Проверяем - слушается ли наш порт:
netstat -tlpn | grep 8008
Внимание: значение порта 8008 задается именно в Listen 127.0.0.1:8008
, его значение в VirtualHost *:8008
будет проигнорировано
Внимание: папка /var/www взята не случайно - у нее уже есть правильный файловый контекст SELinux. При размещении файлов сайтов в другом расположении необходимо будет выставить правильные контексты
Добавим в секцию http
основного файла конфига /etc/nginx/nginx.conf
строку:
server_tokens off;
Создадим вот такой небольшой конфиг для блокировки доступа ботов /etc/nginx/deny_bots.conf
:
if ($http_user_agent ~* SemrushBot|MJ12bot|AhrefsBot|bingbot|DotBot|PetalBot|LinkpadBot|SputnikBot|statdom.ru|MegaIndex.ru|WebDataStats|Jooblebot|Baiduspider|BackupLand|NetcraftSurveyAgent|openstat.ru|fasthttp) {
return 444;
}
Теперь создадим файлы конфигураций наших web-сервисов
/etc/nginx/conf.d/mail.conf
server {
listen 80;
include /etc/nginx/deny_bots.conf;
server_name mail.firstdomain.com;
access_log /var/log/nginx/nginx-mail-access.log;
error_log /var/log/nginx/nginx-mail-error.log;
location / {
proxy_pass http://127.0.0.1:8008/;
proxy_read_timeout 300s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
}
location ~* \.(css|js|png|gif|jpg|jpeg|ico)$ {
root /var/www/mail;
expires 1d;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
/etc/nginx/conf.d/padmin.conf
server {
listen 80;
include /etc/nginx/deny_bots.conf;
server_name postfixadm.firstdomain.com;
access_log /var/log/nginx/nginx-padmin-access.log;
error_log /var/log/nginx/nginx-padmin-error.log;
location / {
proxy_pass http://127.0.0.1:8008/;
proxy_read_timeout 300s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
}
location ~* \.(css|js|png|gif|jpg|jpeg|ico)$ {
root /var/www/padmin;
expires 1d;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Проверяем, запускаем и активируем службу Nginx
nginx -t
systemctl enable nginx --now
Установим certbot. Для его работы необходимо наличие A-записи для нужного домена, указывающие на нашу VPS и правильный конфиг (то есть доступность сайта по http) Nginx+Apache
yum install certbot python2-certbot python2-certbot-nginx
Использование certbot сводится к 2 задачам - первичный выпуск сертификата и периодическое обновление всех сертификатов. При первом запуске Бот спросит соглашение на использование и e-mail админа, кому направлять информацию о статусе сертификатов. После генерации сертификата, certbot автоматически исправит конфиг nginx для использования https вместо http (с переадресацией всех запросов по http на https). Далее в cron поставить certbot renew
для периодического обновления сертификатов. Обновлять его он будет только в случае необходимости.
Теперь настроим mariadb (форк от mysql)
Здесь тоже «слушать» будем на внутреннем localhost-интерфейсе
/etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
bind-address=127.0.0.1
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
/etc/my.cnf.d/server.cnf
[mysqld]
key-buffer=6M
table_cache=256
sort_buffer_size=64K
read_buffer_size=256K
join_buffer_size=1M
read_rnd_buffer_size=256K
net_buffer_length=2K
thread_stack=256K
thread_cache_size=8
max_connection=30
query_cache_type=1
query_cache_limit=1M
query_cache_min_res_unit=1K
query_cache_size=20M
max_heap_table_size=240M
tmp_table_size=300M
log_queries_not_using_indexes=1
slow_query_log=1
slow_query_log_file=/var/log/mariadb/slow_queries.log
long_query_time=3
user=mysql
[isamchk]
key_buffer=8M
sort_buffer_size=8M
[myisamchk]
key_buffer=8M
sort_buffer_size=8M
[innodbchk]
key_buffer=8M
sort_buffer_size=8M
[mysqlhotcopy]
interactive-timeout
# this is read by the standalone daemon and embedded servers
[server]
# this is only for embedded server
[embedded]
# This group is only read by MariaDB-5.5 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mysqld-5.5]
# These two groups are only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]
[mariadb-5.5]
[mariadb-10.0]
Запускаем службу
systemctl start mysql
Инициализируем сервер БД
mysql_secure_installation
Активируем службу
systemctl enable mysql
Dovecot используется для 2х целей:
Устанавливаем софт
yum install dovecot dovecot-mysql dovecot-pigeonhole
Системные требования:
Системные требования (для стабильных версий 1.6.x):
В файле INSTALL см. требования по разворачиванию Roundcube.
И снова 1 запись в DNS для почтового домена и 2 между собой аналогичные для двух других:
В конец файла /var/named/firstdomain.com.zone
добавляем:
@ 300 IN TXT "v=spf1 a mx:mail.firstdomain.com ip4:40.40.40.40 ~all"
mail 300 IN TXT "v=spf1 a mx include:firstdomain.com include:secondomain.org include:thirdomain.ru ip4:40.40.40.40 ~all"
Аналогично в конец файлов /var/named/secondomain.org.zone
и /var/named/thirdomain.ru.zone
:
@ 300 IN TXT "v=spf1 a mx:mail.firstdomain.com ip4:40.40.40.40 ~all"
Важно: проиндексировать параметр Serial в файлах зон
Делаем перезагрузку зон
systemctl reload named-chroot
Расшифровка:
Параметры записи | Описание параметра |
---|---|
@ | использование самого доменного имени |
300 | срок жизни записи TTL |
IN | ключевое слово, дословно - «в» |
TXT | тип записи - TXT |
v=spf1 | версия SPF (актуальная версия 1) |
a | задает для домена разрешенных отправителей |
mx | MaileXchanger - указывается какой адрес FQDN для почтовой службы используется |
include | для каких доменов будет использоваться данный сервер |
ip4 | указывает какой IP-адрес этого сервера (также можно указывать ip6) |
~all | способ обработки спам-писем (на основе классификатора) |
all может принимать варианты:
Вариант | Значение |
---|---|
+all | пропускать все письма |
-all | останавливать все письма, похожие на спам |
~all | маркировать как спам письма, похожие на спам, но пропускать |
Более подробно можно почитать здесь
Для начала необходимо установить, сгенерировать ключи для доменов и т.п.
Установим пакет opendkim
yum install opendkim -y
Далее создадим 2 bash-скрипта:
gendkim.sh
#!/bin/bash
domain=$1
dkimpath=/etc/opendkim/keys
if [ ! -f "$dkimpath/$domain.private" ]; then
opendkim-genkey -D $dkimpath/ -d $domain -s mail
mv $dkimpath/mail.private $dkimpath/$domain.private
mv $dkimpath/mail.txt $dkimpath/$domain.txt
chmod 400 $dkimpath/$domain.private
chown opendkim $dkimpath/$domain.*
fi
testdkim.sh
#!/bin/bash
domain=$1
dkimpath=/etc/opendkim/keys
if [ -f "$dkimpath/$domain.private" ]; then
opendkim-testkey -d $domain -s mail -vvv -k $dkimpath/$domain.private
fi
Делаем их выполняемыми:
chmod 700 gendkim.sh
chmod 700 testdkim.sh
Выпускаем ключи для доменов:
./gendkim.sh firstdomain.com
./gendkim.sh secondomain.org
./gendkim.sh thirdomain.ru
Вносим в конец файла /etc/posfix/main.cf
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Редактируем параметры (раскомменчиваем) /etc/opendkim.conf
Mode sv
Socket inet:8891@localhost
KeyTable /etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
Вносим в конец файла /etc/opendkim/KeyTable
mail._domainkey.firstdomain.com firstdomain.com:mail:/etc/opendkim/keys/firstdomain.com.private
mail._domainkey.secondomain.org secondomain.org:mail:/etc/opendkim/keys/secondomain.org.private
mail._domainkey.thirdomain.ru thirdomain.ru:mail:/etc/opendkim/keys/thirdomain.ru.private
Вносим в конец файла /etc/opendkim/SigningTable
*@firstdomain.com mail._domainkey.firstdomain.com
*@secondomain.org mail._domainkey.secondomain.org
*@thirdomain.ru mail._domainkey.thirdomain.ru
Запускаем и перезапускаем
systemctl enable opendkim --now
systemctl restart postfix
Снова вносим в конец файлов зон TXT-записи (в этот раз содержимое будет одинаковым за исключением <СОДЕРЖИМОЕ ПУБЛИЧНОГО КЛЮЧА>):
mail._domainkey 300 IN TXT "v=DKIM1; g=*; k=rsa; p=<СОДЕРЖИМОЕ ПУБЛИЧНОГО КЛЮЧА>"
<СОДЕРЖИМОЕ ПУБЛИЧНОГО КЛЮЧА> находится в файле /etc/opendkim/keys/<домен>.txt (ключ p=)
Важно: проиндексировать параметр Serial в файлах зон
Делаем перезагрузку зон
systemctl reload named-chroot
Ждем TTL 300 и делаем проверку DKIM:
./testdkim.sh firstdomain.com
./testdkim.sh secondomain.org
./testdkim.sh thirdomain.ru
Ответ должен быть примерно таким:
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/opendkim/keys/firstdomain.com.private
opendkim-testkey: checking key 'mail._domainkey.firstdomain.com'
opendkim-testkey: key OK
Необходимо открыть эти порты на FW
Компонент | Порт | Описание |
---|---|---|
postfix | tcp/25 | SMTP-relay |
postfix | tcp/465 | SMTP TLS |
postfix | tcp/587 | SMTP SSL |
Dovecot | tcp/110 | POP3 |
Dovecot | tcp/143 | IMAP |
Dovecot | tcp/993 | IMAPs |
Dovecot | tcp/995 | POP3s |
BIND | udp/53 | DNS |
BIND | tcp/53 | DNS |
NGINX | tcp/80 | http для certbot |
NGINX | tcp/443 | https для RoundCude/PostfixAdmin |
Виртуальный хостинг вроде должен был бы давно «уйти под воду», но пока в этом мире есть бизнес, который не имеет своего ИТшника, такие услуги не уйдут.
Под облачным провайдером здесь я имею ввиду любого продавца разного рода виртуальных мощностей. Начну по мере повышения стоимости услуг