Привет всем,
Сегодня хотелось бы оставить заметку относительно реализации почтового балансировщика на HAproxy + Keepalived, для балансировки SMTP/IMAP трафика и создания единой клиентской точки доступа к сервисам.
Возможно вам уже известно что Exchange Server не имеет какого либо нативного сервиса для создания отказаусточивости, и как правило почтовую инфраструктуру добавляют дополнительный слой из серверов, которые решают эти проблемы. На практике это могут быть железные балансировщики, например F5 BIG-IP. Или же более простой и дешевый вариант построенный на haproxy.
Этап планирования
Второй вариант может показаться простым в интеграции, но тоже имеет несколько подводных камней которые стоит учесть на этапе пларирования.
TCP vs. HTTP
В первую очередь стоит определиться с режимом (уровнем) балансировки, haproxy может работать как на L4 транспортном уровне работая только с tcp-трафиком, так и на L7 прикладном уровне взаимодействуя с http-запросами.
У каждого из режимов есть свои плюсы/минусы:
- HAproxy в режиме TCP, не выполняет проверку содержимого и соответственно работает быстрее, просто перенаправляя трафик на целевой почтовый сервер и порт. В дополнение очень просто и быстро настраивается и выводиться в продакшен. Из минусов, так как мы не проверяем каждый запрос, то не можем выполнять определенные манипуляции над запросами (банально отсечь), уже на уровне балансировщика. Далее при таком режиме нам доступна только проверка порта. И может произойти такой кейс, когда сервис не будет работать, но порт будет открыт. В таком случаи haproxy будет считать что наш проблемный сервер доступен, и не станет выводить его из балансировки.
- HAproxy в режиме HTTP, при работе в таком режиме мы получаем возможности для более тонкой настройки балансировщика. Проверки доступности сервиса, можно выполнять за счет отправки http-запросов на целевой сервер. Как я и упоминал ранее, за счет просмотра каждого запроса, haproxy может осуществить контроль доступа к определенным службам. Например закрыть доступ к админ-панели Exchange. Да и в целом за счет создания ACL-правил возможно настроить специфичные варианты машрутизации трафика. К дополнительным плюшкам можно добавить реализации SSL, с возможностью использования нескольких ssl-сертификатов.
В процессе тестирования и вывода балансировщиков в прод, мне удалось попробовать оба режима работы. Особой разницы между TCP/HTTP режимами по скорости, я не могу отметить. И после отладки haproxy, все же пришел к http-mode. В дополнение, хочу отметить что переключение балансировщиков в tcp-режим, помогло в траблшутинге проблем связанных с клиенсткими подключениями или NTLM-аутентификацией. По этим причинам, думаю полезно будет поделится обоими версиями конфигураций haproxy.
Использование SSL
SSL Offloading
В выборе режима работы SSL, тоже есть нюансы. Частый пример, который можно встретить это использование SSL Offloading (SSL Разгрузка). Когда SSL-терминирование реализуется на самом балансировщике, haproxy выполняет шифрование/дешифрование запросов и далее проксирует их на целевой сервер в открытом виде по http, тем самым разгружая почтовый сервак. Загвостка состоит в том, что вебсервисы ExchangeServer по умолчанию работают на https и вам необходимо будет перенастроить их на работу http.
SSL Bridging
Второй режим работы SSL называется - SSL Bridging (SSL Мост), в этом случаи haproxy принимая входящие сообщения выполняет их декрипт, и далее для отправки на целевой сервер повторно зашифровывает их. Нюанс кроется в том, что на балансировщике и на exchange должен использоваться один и тот же сертификат. Использование различных сертификатов приведет к ошибкам проверки токена, в следствии чего вызовет проблемы с клиентским доступом. Поэтому при использовании этого режима работы SSL, потребуется выпустить один сертификат с добавлением SAN-объектов или же использовать wildcard-сертификат. В дополнение если планируется использовать ssl-сертификат выпущенный локальным CA, то на серверах-балансировщиках нужно будет обновить рутовый серт, добавив в него сертификаты рутовых/промежуточных локальных центров сертификации.
В этом поинте я остановился на втором варианте, в процессе постараюсь поделится инструкциями как приготовить ssl-сертификат.
Настройка балансировшиков
Время приступать к настройке будушего кластера, собственно схема проекта с которым предстоит работа: На этой схеме имеется два сервера с Exchange Server настроенных в DAG-кластер. Уровнем выше следуют наши балансировшики, на борту каждого крутится haproxy для балансировки почтового трафика, и keepalived для релизации плаваюшего IP. По протоколу VRRP сервера проверяют работоспособность друг-друга. Далее в виде оранжевого облака представлена сущность, это непосредственно наши почтовые клиенты, которые подключаются из внутри скоупа. И наконец, в DMZ-сегменте мы реализуем третий (пограничный/бордер) прокси, задача которого будет прием запросов со стороны внешних клиентов.
Настройка HAproxy
Установка Haproxy
У меня сервера развернуты на базе Almalinux 8.9, и установка haproxy происходит достаточно тривиально из стандартных репозиторириев, командой:
[root@exch-lb01]# yum install -y haproxy
В дополнение, отмечу, что из стандартного списка репозиториев ставится не самая свежая версия программы.
Далее ставим сервис haproxy в автозагрузку:
[root@exch-lb01]# systemctl enable haproxy
И сразу же открываем необходимые порты на фаерволе:
[root@exch-lb01]# firewall-cmd --add-port={25,80,443,143}/tcp --permanent
[root@exch-lb01]# firewall-cmd --reload
Конфигурация для TCP-балансировки
В файл конфигурации haproxy
, добавляем:
[root@exch-lb01]# mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.default
[root@exch-lb01]# vim /etc/haproxy/haproxy.cfg
---
#######################################
# Global settings
#######################################
global
log 127.0.0.1 local0
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
#######################################
# Defaults settings
#######################################
defaults
mode tcp
log global
option redispatch
option log-health-checks
retries 3
#######################################
# Frontend sections
#######################################
frontend fe_exch2019
mode tcp
option tcplog
bind 0.0.0.0:80
bind 0.0.0.0:443
timeout client 1m
default_backend be_exch2019_http
frontend fe_exch2019_smtp
mode tcp
option tcplog
bind 0.0.0.0:25 name smtp
timeout client 1m
# Acl for SMTP
acl smtp_networks src -f /etc/haproxy/haproxy_smtp_whitelist.lst
tcp-request content reject if !smtp_networks
default_backend be_exch2019_smtp
frontend fe_exch2019_imaps
mode tcp
option tcplog
bind *:143 name imap
timeout client 1m
default_backend be_exch2019_imaps
#######################################
# Backend sections
#######################################
backend be_exch2019_http
mode tcp
log global
option tcplog
timeout connect 10s
timeout server 1m
balance roundrobin
server exch01 exch01.mydomain.local:443 weight 75 check
server exch02 exch02.mydomain.local:443 weight 25 check
backend be_exch2019_smtp
mode tcp
log global
option tcplog
timeout connect 10s
timeout server 1m
balance roundrobin
server exch01 exch01.mydomain.local:25 weight 75 check
server exch02 exch02.mydomain.local:25 weight 25 check
backend be_exch2019_imaps
mode tcp
log global
option tcplog
timeout connect 10s
timeout server 1m
balance roundrobin
server exch01 exch01.mydomain.local:143 weight 75 check
server exch02 exch02.mydomain.local:143 weight 25 check
В быстром порядке разберем этот конфиг, здесь представлено четыре контекста.
В глобальном контексте (global
) указываются глобальные настройки для haproxy и используемые здесь параметры выставлены по умолчанию, в будущем здесь мы можем изменить параметр log
, для включения/выключения логирания.
Контекст defaults
содержит общие настройки конторые могут быть унаследованными frontend
, backend
частями. И тут мы оставляем опции:
mode
- режим работы haproxy, в этом конфиге настраиваем haproxy для работы в tcp-mode по умолчаниюlog
- как и писал выше, настраивает логировние сервера. В данном случаниlog global
, говорит ссылаться на опциюlog
в глобальном контексте (global
).option
- с помошью этого параметра мы можем добавить или отключать какие-то фичи в функционале haproxy. Здесь же мы используемoption redispatch
, которая включает функционал ребаланса запросов в случаи недоступности какого-либо бекенда.option log-health-checks
- эта опция включает регистрацию изменений работоспособности бекендов.retries
- этот параметр указывает количество неудачных попыток, после которых бекенд будет считаться недоступным.option tcplog
- устанавливает формат логирования для tcp.
Далее следует контекст, в котором мы описываем frontend
часть. Здесь настраивается внешней интерфейс взаимодействия с haproxy. Тут мы опеределяем режим работы (http/tcp mode), адрес и порт на котором haproxy будет принимать коннекты. В нашем же случаи представлено описание трех frontend
секций с именами - fe_exch2019
, fe_exch2019_smtp
, fe_exch2019_imap
.
Каждый из фронтов содержит почти одинаковый набор параметров:
mode tcp
- определяет режим работы конкретного фронта. По идеи, мы можем не указывать этот параметр, так как выше вdefaults
он уже определен. Но все же негласно, принято и в каждой секции его указывать. Возможно это сделано для читаемости…bind 0.0.0.0:443
- bind определяет, на каком порты и адресе будет работает конкретный фронтенд.timeout client 1m
- данный параметр указывает, в течении какого времени неактивная сессия будет разорвана клиентом. По умолчанию сессия держится около 5 минут, но принято уменьшать таймаут.
Во фронде fe_exch2019_smtp
использован acl, для разграничения доступа к smtp-сервису.
# Acl for SMTP
acl smtp_networks src -f /etc/haproxy/haproxy_smtp_whitelist.lst
tcp-request content reject if !smtp_networks
Аксесс лист определяется ключевым словом acl
, затем следует название листа smtp_networks
. После определяется источник src
с опцией -f
, которая приказывает взять данные из файла.
Далее указывается инструкция, при которой все новые сессии будут обрыватся, если же адрес клиента не содержится в файле acl.
Последняя директива в каждом фронте это - default_backend
, с помошью ее мы выбираем какой бекенд использовать по умолчанию.
Завершающим элементом нашей конфиги, следуем контекст backend
, он содержит настройки пула серверов, на которые haproxy будет маршрутизировать трафик. Здесь также имеется три бекенда с именами - be_exch2019_http
, be_exch2019_smtp
, be_exch2019_imap
. Внутри каждого следуют уже знакомые директивы, и добавляется несколько новых:
timeout connect 10s
- этот параметр задает максимальное время в течении которого haproxy будет пытатся поднять сессию с бекендом. Если ваши сервера размещаны в разных сетевых сегментах, или dmz-зонах, то рекомендуется увеличивать значение времени. Не рекомендуется устанавливать значение менее 5 секунд.timeout server 1m
- с помошью данного параметра мы устанавливаем таймаут на бездействие со стороны сервера. В течении установленного времени сервер должен будет отправить какие-либо данные, иначе сессия будет разорвана.balance roundrobin
- данная директива настраивает тип балансировки запросов. В данном случаи мы используем типroundrobin
, при которой каждый сервер будет используется по очередности.
В конце данного контекста описываются пулл с серверами Exchange, на которые haproxy будет распределять запросы.
server
- каждый сервер в пуле определяется с помошью этого аргумента. Далее указывается имя (alias) участника данного пула. И затем мы указываем IP-адрес/Доменное имя сервера и порт.weight
для каждого мембера в конце приписывается параметр веса, при работе бекенда в режиме roundrobin, логика распределения запросов такова что большая часть запросов будет отправлена на сервер с наибольшим числом веса.check
эта опция нужна для проверки доступности сервера.
Синтаксис описания участника пула такой:
<Аргумент> <Имя/Alias> <IP-адрес/Domain сервера и порт> <Вес сервера> <Проверка>
server exch01 exch01.mydomain.local:143 weight 75 check
Сохраняем конфигурацию, и далее создадим отдельный файл, в котором будут содержаться ip-адреса хостов, которым разрешено использование SMTP.
[root@exch-lb01]# vim /etc/haproxy/haproxy_smtp_whitelist.lst
---
10.8.5.17/32
10.8.5.17/32
...
Для запуска haproxy все готово, для проверки рабоспособности конфигурации можно воспользоваться командой:
[root@exch-lb01]# haproxy -c -V -f /etc/haproxy/haproxy.cfg
Перезапускаем сервис:
[root@exch-lb01]# systemctl restart haproxy
Конфигурация для HTTP-балансировки
В ниже представной конфиге используется сетап с SSL-мостом, где для успешной работы балансировщика нам нужно приготовить один ssl-сертификат, который должен быть установлен на почтовых серверах и на нодах-балансировщиках. Если у вас есть wildcard-сертификат, то нет никаких проблем и можно использовать его.
В моем же случаи балансировщики будут работать внутри инфраструктуры, без доступа со внешки. Соответственно используемый мной ssl-сертификат выпущен локальным CA, с добавлением дополнительных SAN-объектов.
Собственно сам конфиг:
#######################################
# Global settings
#######################################
global
log 127.0.0.1:514 local0
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
#######################################
# Defaults settings
#######################################
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option httpclose
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 15s
timeout queue 1m
timeout connect 10s
timeout client 15m
timeout server 15m
timeout http-keep-alive 10s
timeout check 10s
maxconn 100000
#######################################
# Frontend sections
#######################################
frontend fe_exch2019
http-response set-header X-Frame-Options SAMEORIGIN
http-response set-header X-Content-Type-Options nosniff
http-response set-header Strict-Transport-Security max-age=63072000
option http-keep-alive
timeout client 30s
mode http
bind *:80
bind *:443 ssl crt /etc/ssl/certs/exch.pem
# Redirect from 80 -> 443
redirect scheme https code 301 if !{ ssl_fc }
# Acl for Exchange Admin Center
acl admins_network src -f /etc/haproxy/haproxy_ecp_whitelist.lst
acl ecp_service url_beg /ecp
http-request deny if ecp_service !admins_network
# Acl for OWA
acl users_networks src -f /etc/haproxy/haproxy_owa_whitelist.lst
acl owa_service url_beg /owa
acl owa_service url_beg /OWA
http-request deny if owa_service !users_networks
# Acl for assign backend
acl autodiscover url_beg /Autodiscover
acl autodiscover url_beg /autodiscover
acl autodiscover url_beg /AutoDiscover
acl eas url_beg /Microsoft-Server-ActiveSync
acl eas url_beg /Microsoft-Server-activeSync
acl mapi url_beg /mapi
acl rpc url_beg /rpc
acl owa url_beg /owa
acl owa url_beg /OWA
acl ecp url_beg /ecp
acl ews url_beg /EWS
acl ews url_beg /ews
acl oab url_beg /OAB
# Backend assign
use_backend be_exch2019_autodiscover if autodiscover
use_backend be_exch2019_mapi if mapi
use_backend be_exch2019_rpc if rpc
use_backend be_exch2019_owa if owa
use_backend be_exch2019_eas if eas
use_backend be_exch2019_ecp if ecp
use_backend be_exch2019_ews if ews
use_backend be_exch2019_oab if oab
# Backend by default
default_backend be_exch2019_owa
frontend fe_exch2019_smtp
mode tcp
option tcplog
bind *:25 name smtp
# Acl for SMTP
acl smtp_networks src -f /etc/haproxy/haproxy_smtp_whitelist.lst
tcp-request content reject if !smtp_networks
default_backend be_exch2019_smtp
frontend fe_exchange_imaps
mode tcp
option tcplog
bind *:143 name imap
default_backend be_exchange_imaps
#######################################
# Backend sections
#######################################
backend be_exch2019_autodiscover
mode http
balance source
timeout server 30s
timeout connect 4s
option http-keep-alive
option prefer-last-server
option httpchk GET /Autodiscover/HealthCheck.htm
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_mapi
mode http
balance source
timeout server 30s
timeout connect 4s
option http-keep-alive
option prefer-last-server
option httpchk GET /mapi/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_rpc
mode http
balance source
option http-keep-alive
option prefer-last-server
option httpchk GET /rpc/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_owa
mode http
option http-keep-alive
option prefer-last-server
option httpchk GET /owa/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_eas
mode http
option http-keep-alive
option prefer-last-server
option httpchk GET /microsoft-server-activesync/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_ecp
mode http
option http-keep-alive
option prefer-last-server
option httpchk GET /ecp/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_ews
mode http
balance source
option http-keep-alive
option prefer-last-server
option httpchk GET /ews/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_oab
mode http
balance roundrobin
option http-keep-alive
option prefer-last-server
option httpchk GET /oab/healthcheck.htm
option log-health-checks
http-check expect status 200
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019
mode http
balance roundrobin
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
backend be_exch2019_smtp
mode tcp
balance roundrobin
option log-health-checks
server exch01 exch01.mydomain.local:25 weight 75 check
server exch02 exch02.mydomain.local:25 weight 25 check
backend be_exchange_imaps
mode tcp
balance leastconn
option log-health-checks
server exch01 exch01.mydomain.local:143 weight 75 check
server exch02 exch02.mydomain.local:143 weight 25 check
В Global settings
по большей части все параметры уже были выставлены по умолчанию. За исключением, включения опции логирования.
log 127.0.0.1:514 local0
Здесь мы перенаправляем весь вывод на локальный rsyslog-сервер. Далее в настройках rsyslog-сервера добавим правила, что бы события по haproxy записывались в отдельный файл:
[root@exch-lb01]# vim /etc/rsyslog.conf
---
# RULES:
local0.* /var/log/haproxy.log
local0.notice /var/log/happroxy-notice.log
В дополение к этому добавились опции определяющие политики криптошифрования:
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
На раннем этапе я не стал заморачиваться с выбором SSL/TLS - профилей, оставил системный. В будущем это можно будет допилить для исключения старых и не безопасных версий TLS/SSL.
Defaults settings
- внутри этого контекста уже видны изменения в параметрах, собственно во первых по умолчанию мы включаем режим работы haproxy - http
. По мимо уже известных нам параметров, определяем:
option httplog
- включаем расширенное логирование для http;option dontlognull
- не логируем пустые (null) соединения;option http-server-close
- эта опция включает на сервере режим автоматического закрытия http-соединения, путем добавления заголовкаclose
;option httpclose
- с этой опцией сервер проверяет каждое соединение на наличие заголовкаclose
, и там где он отсутствует добавляет;option forwardfor
- включаем добавление заголовкаX-Forwarded-For
, за исключением адресов в этом диапазоне127.0.0.0/8
;timeout http-request
- устанавливает максимальное время ожидаения на выполнение запроса. То есть если с клиент установил сессию и не отпраляет данные в течении установленного таймаута, то сессия будет разорвана.timeout queue
- таймаут на максимальное время ожидания в очереди на свободный connection slot. Например, если на сервере привышено количество сессий, новые сессии будут падать в очередь на свободный слот. И далее по достижению этого таймаута, если не получат слот, то будут отброшены.timeout http-keep-alive
- определяем таймаут, в течении которого сервер будет держать сессию открытой.timeout check
- дополнильные таймаут на соединение, которое уже было установлено.maxconn
- максимальное количество одновременных соединений, которое может быть обработано одним фронтендом. При увеличении количества одновременных сессий, стоит учитывает размер оперативной памяти. Например, системе с 40000-50000 одновременными конекшенами потребуется около 1gb памяти.
Frontend sections
- в контексте описания фронтов у нас имеется три фронтенда - fe_exch2019
, fe_exch2019_smtp
, fe_exch2019_imaps
. Последнии два фронта мы рассмотрели ранее, они просто перенаправляют tcp-запросы на почтовые бекенды.
Фронтенд fe_exch2019
работает в режиме http, и выполняет логику по перераспределения запросов почтовым сервисам. В его настройки включены параметры:
http-response
- данная опция добавляет заголовки базовой http-безопасности перед отправкой ответа обратно клиенту.
http-response set-header X-Frame-Options SAMEORIGIN
http-response set-header X-Content-Type-Options nosniff
http-response set-header Strict-Transport-Security max-age=63072000
option http-keep-alive
иtimeout client
- эти два параметра настраивают удержание сессии между haproxy и клиентом. И в случаи если клиент неактивен в течении 30 секунд, сессия будет считаться разорваной.
option http-keep-alive
timeout client 30s
Для корректности работы NTLM-аутентификации, эти параметры необходимы.
mode
,bind
- Выбор режима работы данного фронтенда, и настройка сетевого сокета:
mode http
bind *:80
bind *:443 ssl crt /etc/ssl/certs/exch.pem
Здесь мы определяем порты, на которых данный фронтенд будет обрабатывать запросы. К порту 443
, добавляем опцию ssl
, и указываем сертификат. (Как и упоминал ранее, сертификат должен быть только такой же как и на почтовых серверах).
redirect
- перенаправление на ssl порт
redirect scheme https code 301 if !{ ssl_fc }
Тут мы просто перенаправляем запросы с http на https.
acl
,http-request deny
- далее в конфиге следует два отдельных блока с правилом блокироки http-запроса.
# Acl for Exchange Admin Center
acl admins_network src -f /etc/haproxy/haproxy_ecp_whitelist.lst
acl ecp_service url_beg /ecp
http-request deny if ecp_service !admins_network
В данном случаи в первом access листе из стороннего файла определяем ip-адреса клиентов, которым разрешен доступ на панель управления Exchange Server. Во втором acl определяем uri-path до сервиса ecp
. Затем после access-листов устанавливаем запрещающее действие. То есть все запросы на uri /ecp
, от клиентов которые не определены в файле /etc/haproxy/haproxy_ecp_whitelist.lst
будут отброшены.
Эти правила закрывают доступ на веб-версию outlook.
# Acl for OWA
acl users_networks src -f /etc/haproxy/haproxy_owa_whitelist.lst
acl owa_service url_beg /owa
acl owa_service url_beg /OWA
http-request deny if owa_service !users_networks
Этот блок правил является опциональным, его можно вообще не использовать. Но все же я стараюсь закрывать излишний функционал. По своей логике тут происходит аналогичная магия. Определяется список ip клиентов, котором доступ на ресурс /owa
разрешен. И далее запрешающее всем действие.
Следом определяется другая группа ACL, в последующем при помощи этих правил будем выполнять выбор соостветствующего бекенда.
# Acl for assign backend
acl autodiscover url_beg /Autodiscover
acl autodiscover url_beg /autodiscover
acl autodiscover url_beg /AutoDiscover
acl eas url_beg /Microsoft-Server-ActiveSync
acl eas url_beg /Microsoft-Server-activeSync
acl mapi url_beg /mapi
acl rpc url_beg /rpc
acl owa url_beg /owa
acl owa url_beg /OWA
acl ecp url_beg /ecp
acl ews url_beg /EWS
acl ews url_beg /ews
acl oab url_beg /OAB
Параметр url_beg
, проверяет начинается ли uri-запроса со значения которое у него указано. Если совпадет, то acl-правилу будет присвоено другое значание true
.
Собственно в этом блоке работает логика распределения запросов по бекендам:
# Backend assign
use_backend be_exch2019_autodiscover if autodiscover
use_backend be_exch2019_mapi if mapi
use_backend be_exch2019_rpc if rpc
use_backend be_exch2019_owa if owa
use_backend be_exch2019_eas if eas
use_backend be_exch2019_ecp if ecp
use_backend be_exch2019_ews if ews
use_backend be_exch2019_oab if oab
Здесь все просто, если значение любой переменной true
, тогда использовать бекенд с определенным именем. Например, если значение переменной owa
является истиной, тогда запрос будет перенаправлен на бекенд с именем - be_exch2019_owa
.
В случаи если не по одному правилу для запроса не был определен бекенд, то мы перенаправляем запрос на бекенд который будет использоваться по умолчанию:
# Backend by default
default_backend be_exch2019_owa
Последняя секция Backend sections
, содержит список бекендов для веб-сервисов почты, smtp и imap. Не будет рассматривать их всех, рассмотрим только один, так как почти у всех использованы аналогичные параметры.
Бекенды для почтовых веб-сервисов все работают в режиме http
. Используемый алгоритм балансировки balance source
, означает что выбор бекенд сервера будет основан на хеше ip-адреса клиента. И при совпадении его, запрос клиента будет перенаправлен на один и тот же бекенд-сервер.
Для корретной авторизации и работы NTLM-аутентификации нужны эти параметры:
option http-keep-alive
option prefer-last-server
option http-keep-alive
- сохраняет состояние сессии между сервером и клиентом определенное время. А параметр option prefer-last-server
- нужен для того, чтобы запросы были направлены на один и тот же сервер в рамках одного сеанса.
Эти параметры нужны для проверки доступности веб-сервера.
option httpchk GET /Autodiscover/HealthCheck.htm
http-check expect status 200
С помошью параметра option httpchk
отправляется GET-запрос по адресу сервера сервера с uri - /<ExchangeService>/HealthCheck.htm
. http-check expect status 200
- этот параметр проверяем статус код проверки. В данном случаи он должен быть со статусом HTTP 200.
Описание бекендов завершается с определением пула серверов:
server exch01 exch01.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
server exch02 exch02.mydomain.local:443 check ssl inter 15s verify required ca-file /etc/pki/tls/certs/ca-bundle.crt
Тут мы определяем два сервера exch01
, exch02
.
check ssl
- включает проверку доступности серверов поверх ssl.inter 15s
- задает интервал между проверками.verify required
- при использовании этого параметра haproxy будет запрашивать ssl-сертификат у бекенд сервера.ca-file /etc/pki/tls/certs/ca-bundle.crt
- данная директива указывает, какой рутовый сертификат будет использоваться для проверки подлиности ssl-сертификатов сервера.
Собственно с конфигом на этом этапе все. Остаеться только создать файлы /etc/haproxy/haproxy_owa_whitelist.lst
и /etc/haproxy/haproxy_ecp_whitelist.lst
, в файлы необходимо добавить ip-адреса которым разрешен доступ на OWA и ECP.
И еще один момент, если вы тоже используете ssl-сертификат выпушенный локальным CA, то не забудьте добавить его в рутовый серт на сервере:
[root@exch-lb01]# yum install -y ca-certificates
[root@exch-lb01]# cp /root/mydomain-root.ca /etc/pki/ca-trust/source/anchors/mydomain-root.ca
[root@exch-lb01]# update-ca-trust
Ну и теперь можем проверить конфигу, и запустить балансироващик.
Настройка Keepalived
Итак, мы проработали вопрос балансировки почтовых запросов на сервера, определив для себя оптимальный сетап. В этом разделе нам предстоит поработать над созданием единой точки входа для наших почтовых клиентов.
На оба сервера с haproxy устанавливаем пакет - keepalived
:
[All Servers]$ yum install keepalived -y
Для создания схема active/passive напишем две конфига. Конфиг для основного сервера:
[root@exch-lb01]# vim /etc/keepalived/keepalived.conf
---
global_defs {
enable_script_security
script_user haproxy
}
vrrp_script haproxy_check {
script "/usr/bin/systemctl is-active haproxy >/dev/null && echo 1 || echo 0"
interval 5
}
vrrp_instance EMAIL_VIP1 {
state MASTER
interface ens192
virtual_router_id 233
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass Mypassword
}
virtual_ipaddress {
10.12.8.15
}
track_script {
haproxy_check
}
}
И конфиг для бекапного сервера:
[root@exch-lb02]# vim /etc/keepalived/keepalived.conf
---
global_defs {
enable_script_security
script_user haproxy
}
vrrp_script haproxy_check {
script "/usr/bin/systemctl is-active haproxy >/dev/null && echo 1 || echo 0"
interval 5
}
vrrp_instance EMAIL_VIP1 {
state BACKUP
interface ens192
virtual_router_id 233
priority 75
advert_int 1
authentication {
auth_type PASS
auth_pass Mypassword
}
virtual_ipaddress {
10.12.8.15
}
track_script {
haproxy_check
}
}
В обоих конфигурационных файлах у нас имеется одна проверка - haproxy_check
, если скрипт в контексте данной проверки не выполняется, то интенс переводится а аварийный режим. И кластерный ip-адрес будет перехвачен резервной нодой.
На нодах в настройках фаервола разрешаем arp:
[All Servers]$ firewall-cmd --permanent --add-rich-rule='rule protocol value="vrrp" accept'
[All Servers]$ firewall-cmd --reload
Ну и запускаем keepalived:
[All Servers]$ systemctl enable --now keepalived
На этом все, постарался понятно и подробно расписать процесс настройки балансировщиков.
Далее я прикрутил экспортера для сбора метрик, в прометеус. Очень удобно оказалось мониторить почту, и видить какие либо проблемы или отклонения по графикам.
И в дополнение все действия по обновлению и настройкам перенес в puppet+gitlab. Теперь когда мне нужно обновить какой либо параметр в конфиге haproxy/keepalived, я просто меняю шаблон конфига в гитлабе и пушу все на сервера. Далее паппет все сам настроит. Очень удобно, так как не надо ходить на какдый сервер и все ручками править.