Балансировка нагрузки SMTP с передачей IP удаленного хоста на SMTP-серверы.

Вопрос или проблема

Я пытаюсь создать кластер SMTP с балансировкой нагрузки. Почтовые серверы уже существуют и работают на Exim 4. Изначально я рассмотрел возможность использования Nginx для балансировки нагрузки, однако на тестовой системе все почтовые серверы видят входящие соединения как исходящие от IP балансировщика, а не от фактического удаленного отправителя. После обширного поиска в Google не оказалось способа обойти это. Поскольку это фактически превращает кластер почты в открытый релей, это, очевидно, не подходит, что жаль, так как Nginx в остальном работает прекрасно.

Поэтому я рассматриваю возможность использования HAProxy, так как, судя по дальнейшему поиску в Google, у него есть возможность передавать соединения с их оригинальным исходным IP, так что списки разрешенных реле и ACL будут работать корректно.

Однако, настроив HAProxy согласно нескольким онлайн-примером, я либо получаю “Ошибка синхронизации SMTP” (и 500-ю ошибку, поэтому почта будет отклонена) с немедленным разрывом соединения, либо просто разрыв соединения без каких-либо сообщений SMTP.

Вот haproxy.conf, который используется:

global

    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        nobody
    group       nobody
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    log                     global
    option                  redispatch
    retries                 3
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout check           10s
    maxconn                 3000

listen smtp
    bind 0.0.0.0:25
    mode tcp
    no option http-server-close
    balance roundrobin
#    option smtpchk HELO smtp-in.example.com
    server smtp01 10.0.0.141:25 send-proxy check
    server smtp02 10.0.0.143:25 send-proxy check

Несмотря на наличие команды send-proxy, которая, как я понимаю, указывает haproxy передавать исходный IP, логи Exim выглядят так:

016-12-26 07:06:48 Ошибка синхронизации протокола SMTP (входные данные отправлены без ожидания приветствия): отклоненное соединение от H=[10.0.0.150] input=”PROXY TCP4 10.0.0.150 10.0.0.143 40334 25\r\nHELO smtp-in.example.com\r\n”

В этом случае .150 — это IP балансировщика, а .143 — это SMTP сервер Exim.

Вопросы:

  1. Возможно ли действительно заставить Nginx представлять SMTP соединения для почтовых серверов с исходным IP от реального удаленного источника, а не от балансировщика?

  2. Кроме того, возможно ли это в HAProxy и как это делается?

В данном случае текущая производственная система работает на LVS, однако она зависит от того, чтобы и балансировщик нагрузки, и интерфейсы обратной связи на всех почтовых серверах имели один и тот же IP-адрес. Новый балансировщик нагрузки будет на OpenSUSE 42.2, и, среди прочего, если он обнаруживает IP, который уже используется в сети, он кажется, с благодарностью удаляет его с себя, чтобы избежать конфликта. Поэтому LVS не подходит для новейшей сборки.

Другие решения проблемы, которые я рассматриваю, включают полное разделение входящего и исходящего SMTP-трафика (в настоящее время все проходит через один и тот же балансировщик нагрузки), установку простого реле (возможно, qmail) на IP-адрес балансировщика нагрузки, настроенного только на разрешенные диапазоны согласно стандартной практике реле, и использование простого DNS раунд-робина в записях MX для отправки входящих SMTP напрямую на почтовые серверы. Но решение с балансировкой нагрузки будет более элегантным.

Я использовал пользовательскую проверку tcp следующим образом

backend smtp-back
    mode tcp
    no option http-server-close
    balance roundrobin
    tcp-check expect string 220
    tcp-check send HELO\ test\r\n
    tcp-check expect string 250
    tcp-check send QUIT\r\n
    tcp-check expect string 221
    server mail01  mail01:25 check inter 60s rise 3 fall 3 backup
    server mail02  mail02:25 check inter 60s rise 3 fall 3 backup

(переведено из комментария):

Совсем не нужно запускать балансировщик нагрузки перед вашим кластером SMTP. Балансировка нагрузки и возврат из недоступных MX — это неотъемлемая часть SMTP. См. RFC 2821 пункт 5. Разрешение адресов и обработка почты для подробностей.

Просто введите все имена хостов в вашу запись MX с одинаковым приоритетом или используйте единственную запись MX с раунд-робин DNS за ней.

Ответ или решение

Для создания кластера SMTP с балансировкой нагрузки, который корректно передает исходный IP-адрес удаленных отправителей, необходимо учесть несколько ключевых моментов и правильно настроить используемое ПО. Я рассмотрю оба вопроса в вашем запросе.

1. Использование Nginx для передачи исходного IP

На данный момент Nginx не предоставляет функционала для корректной работы с SMTP, как это может сделать HAProxy, так как Nginx в основном ориентирован на HTTP/HTTPS-трафик. Хотя в Nginx есть поддержка TCP-соединений, она не всегда надежна для работы с протоколами, отличными от HTTP, особенно в SMTP. Таким образом, использование Nginx в вашем случае не рекомендуется, так как он не сможет правильно передать исходный адрес отправителя.

2. Настройка HAProxy для работы с SMTP

HAProxy предлагает зрелую и проверенную методику балансировки нагрузки для таких приложений, как SMTP. Ваша конфигурация HAProxy включает команду send-proxy, что правильно, так как именно она позволяет передавать исходный IP-адрес клиента. Однако вы столкнулись с ошибкой "SMTP protocol synchronization error".

Вот несколько шагов и корректировок для решения вашей проблемы:

Исправленная конфигурация HAProxy:

global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        nobody
    group       nobody
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    log                     global
    option                  redispatch
    retries                 3
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    maxconn                 3000

frontend smtp_front
    bind 0.0.0.0:25
    mode tcp
    option tcplog
    default_backend smtp_back

backend smtp_back
    mode tcp
    option tcp-check
    balance roundrobin
    server smtp01 10.0.0.141:25 send-proxy check
    server smtp02 10.0.0.143:25 send-proxy check

Объяснение изменений:

  1. Разделение frontend и backend: Используйте секцию frontend для настройки точки входа (в данном случае SMTP на порту 25) и backend для управления серверами SMTP.

  2. Опция option tcplog: Это необходимо для логирования TCP-трафика, что упростит отладку.

  3. Удалённый smtpchk: Замените smtpchk на tcp-check, чтобы правильно проверять работоспособность серверов в бэкенде.

Проверка конфигурации Exim

Убедитесь, что Exim на каждом из ваших SMTP-серверов настроен правильно для работы с "PROXY" заголовком, который используется HAProxy для передачи IP-адресов. Обычно это связывается с настройкой "daemon_options" и "acl".

Пример настройки в Exim:

acl_smtp_connect = acl_smtp_connect
acl_smtp_connect = acl_check_connect

acl_check_connect:
  accept  hosts = 0.0.0.0/0  # Разрешить все IP для тестирования
  deny    !hosts = 0.0.0.0/0

Заключение

Если все настроено правильно, вы должны получить балансировку нагрузки между вашими серверами SMTP с корректной передачей исходного IP-адреса. Если возникают дополнительные ошибки, смотрите журналы HAProxy и Exim для более детального анализа. В случае если часть инфраструктуры меняется, стоит подумать о доменной балансировке через DNS, что также может упростить задачу, однако использование HAProxy обеспечивает более надежную и контролируемую среду.

Оцените материал
Добавить комментарий

Капча загружается...