Подключение к SMTP-серверу на localhost:25 без аутентификации?

Какие правильные настройки нужно передать в ./discourse-setup для подключения к SMTP-серверу на localhost:25 без аутентификации?

Меня очень удивляет, что это не поддерживается из коробки (OOTB); это конфигурация по умолчанию в большинстве установок Linux.

Мой сервер локально запускает postfix; он недоступен из Интернета. Он работает нормально, например, при выполнении команды mail. Я нашел несколько неофициальных руководств в Интернете, предлагающих изменения в /var/discourse/containers/app.yml, и в итоге смог установить и запустить его со следующими настройками:

  DISCOURSE_SMTP_ADDRESS: localhost
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: discourse@opensouceecology.org
  DISCOURSE_SMTP_PASSWORD: "none"
  DISCOURSE_SMTP_AUTHENTICATION: none
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_ENABLE_START_TLS: false

Обратите внимание, что если я omit переменные DISCOURSE_SMTP_USER_NAME или DISCOURSE_SMTP_PASSWORD, скрипт установки ругается, утверждая, что они обязательны (баг?).

А теперь, когда я нажимаю кнопку «Отправить письмо активации повторно» в веб-интерфейсе Discourse, в файле журнала (/var/discourse/shared/standalone/log/rails/production.log) появляется следующая запись:

Started PUT "/finish-installation/resend-email" for 127.0.0.1 at 2019-11-07 13:15:31 +0000
Processing by FinishInstallationController#resend_email as HTML
  Parameters: {"authenticity_token"=>"SzQCvRWiqdXsBKzOjIB0X7KkvXro7Od6SdP8Qa8vvrskPeNYZNos5ORHJfyDUrHiKShZR/txM6NHuqHHCQCR1w=="}
  Rendering finish_installation/resend_email.html.erb within layouts/finish_installation
  Rendered finish_installation/resend_email.html.erb within layouts/finish_installation (Duration: 0.7ms | Allocations: 103)
  Rendered layouts/_head.html.erb (Duration: 0.5ms | Allocations: 103)
Completed 200 OK in 98ms (Views: 3.0ms | ActiveRecord: 0.0ms | Allocations: 4763)
  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.5ms | Allocations: 141)
Delivered mail c4ca58ca-345e-46c4-81bc-6d0eac7afa04@discourse.opensourceecology.org (11.3ms)
Job exception: wrong authentication type none

…Но мой тип аутентификации именно ‘none’. Какое должно быть правильное значение для отсутствия аутентификации?

РЕДАКТИРОВАНИЕ: также, может ли кто-нибудь дать ссылку на документацию, определяющую все возможные переменные “DISCOURSE_SMTP_*” и все их допустимые значения?

РЕДАКТИРОВАНИЕ 2: это оказывается гораздо сложнее, чем должно быть. Я думаю, что ‘localhost’ внутри контейнера Docker разрешается в сам контейнер Discourse (app), а не в хост Docker, на котором запущен мой SMTP-сервер postfix. Это усложняется ещё и настройками mynetworks и iptables postfix (которые были настроены скриптом discourse-setup или его дочерними скриптами). Какое правильное конфигурационное решение здесь, чтобы просто заставить Discourse использовать SMTP-сервер, на котором я хочу запустить Discourse, без аутентификации SMTP?

Думаю, это уже около 20 лет не совсем верно.

Вы не можете использовать discourse-setup для таких случаев, как ваш, поскольку очень мало людей используют SMTP-серверы без пароля, даже за брандмауэром.

Что бы я сделал, так это настроил пароли SMTP для моего почтового сервера. На самом деле существенных недостатков тут нет.

Если вы не хотите этого делать, я думаю, что вместо «none» для аутентификации лучше указать «» (аналогично для пароля и имени пользователя).

Я тоже так думаю. Попробуйте использовать имя контейнера. Думаю, вам нужно убедиться, что оба они находятся в одной сети Docker.

В 2019 году это конфигурация по умолчанию для postfix в RHEL/CentOS. Postfix привязывается только к петлевому интерфейсу и отбрасывает все SMTP-запросы, которые не исходят из 127.0.0.0/8. Аутентификация не требуется. Насчёт Debian я не уверен, но, думаю, exim имеет аналогичную конфигурацию по умолчанию.

Несколько тем на этих форумах от других пользователей, столкнувшихся с этой проблемой:

Похоже, что темы о том, как настроить это в RHEL/CentOS с необходимыми изменениями как в Discourse, так и в postfix, нет, поэтому я документирую это здесь.

Похоже, что это невозможно сделать с помощью скрипта discourse-setup, но мне удалось заставить это работать.

Сначала мне нужно было определить IP-адрес хоста Docker так, как его видит контейнер Docker. Использование 127.0.0.1 не сработает, потому что контейнер Docker воспримет 127.0.0.1 как себя. Вместо этого нам нужно указать IP-адрес или имя хоста Docker-хоста, на котором запущен SMTP-сервер postfix, и который доступен для контейнера Docker (например, не внешний IP-адрес вашего Docker-хоста, если вы не хотите, чтобы ваш SMTP-сервер был доступен из интернета).

Я извлек соответствующий IP-адрес хоста Docker (172.17.0.1) из интерфейса docker0, выполнив на хосте Docker следующую команду:

[maltfield@osestaging1 ~]$ ip address show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:80:35:65:a1 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:80ff:fe35:65a1/64 scope link 
       valid_lft forever preferred_lft forever
[maltfield@osestaging1 ~]$

Затем я отредактировал yaml-файл моего приложения Discourse, установив значение “DISCOURSE_SMTP_ADDRESS” в 172.17.0.1 из вышеприведённого.

[maltfield@osestaging1 ~]$ cd /var/discourse/
[maltfield@osestaging1 discourse]$ grep SMTP containers/app.yml
  DISCOURSE_SMTP_ADDRESS: 172.17.0.1
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_AUTHENTICATION: none
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_ENABLE_START_TLS: false
[maltfield@osestaging1 discourse]$ 

Обратите внимание, что сначала я попытался использовать внутреннее имя хоста Docker host.docker.internal, но, похоже, это имя хоста недоступно для пользователей Docker в Linux.

Поскольку конфигурация postfix по умолчанию в RHEL/CentOS привязывается только к 127.0.0.1 (что хорошо), вам нужно изменить /etc/postfix/main.cf, чтобы он также привязывался к интерфейсу docker0, и добавить эту подсеть в группу mynetworks, чтобы SMTP-трафик, поступающий из контейнеров Docker, принимался postfix.

[maltfield@osestaging1 postfix]$ grep -ir '172.17' /etc/postfix/*
/etc/postfix/main.cf:inet_interfaces = 127.0.0.1, 172.17.0.1
/etc/postfix/main.cf:mynetworks = 127.0.0.0/8, 172.17.0.0/16
[maltfield@osestaging1 postfix]$ 

После этих изменений пересоберите Discourse, и теперь он должен уметь отправлять электронные письма через postfix вашего Docker-хоста.

/var/discourse/launcher rebuild app

Хотя это работает, у меня есть несколько вопросов:

  1. Существует ли какая-то другая переменная окружения или имя хоста, которые уже указывают на Docker-хост (172.17.0.1 в данном случае)?

Я заметил, что переменная окружения DISCOURSE_HOST_IP «внедряется» launcher. Возможно ли установить ключ yaml DISCOURSE_SMTP_ADDRESS в то же значение, что и другой ключ yaml, используя что-то вроде этого?

DISCOURSE_SMTP_ADDRESS: $DISCOURSE_HOST_IP
  1. В целом, насколько стабилен IP-адрес 172.17.0.1 Docker-хоста? Всегда ли это этот IP в системах RHEL/CentOS? Может ли он когда-нибудь измениться?

@maltfield Просто хотел сказать спасибо за инструкции.

Я столкнулся с той же проблемой на Debian… Можно, конечно, создать отдельного почтового пользователя для Discourse и настроить подключение и вход на порт 465 сайта, но, на мой взгляд, подключение к порту 25 изнутри более логично.

Кстати, на Debian 10 с docker.io из репозиториев docker0 всё ещё имеет адрес 172.17.0.1/16.

Возможно, вы неправильно понимаете, что говорит @maltfield?

Насколько я помню (а это уходит дальше, чем на 20 лет назад), в системах Linux (/ Unix / BSD / Solaris) всегда работал SMTP-сервер, который по умолчанию настроен так, чтобы без вопросов ретранслировать всё, полученное с localhost. Это избавляет любые другие приложения, работающие на этой машине, от необходимости самостоятельно беспокоиться о настройке параметров SMTP.

Да, большинству серверов Linux не требуется аутентификация для отправки почты (либо по умолчанию, либо после установки и настройки). Это также не обязательно, если они не выполняют ретрансляцию за пределы локальной сети. Скрипты установки Discourse по умолчанию не подойдут для большинства серверов. Они разработаны для узкого набора облачных решений на базе Docker.

Вы можете прочитать мои полные подробные инструкции по установке Discourse на выделенный физический сервер под управлением RHEL/CentOS 7 в вики Open Source Ecology. Обратите внимание на раздел о SMTP здесь:

Ну, я почти всегда полагаюсь на ваше мнение в таких вопросах! Видимо, прошло уже много лет с тех пор, как я запускал SMTP-сервер на localhost, так что, скорее всего, я не совсем понимаю, о чём говорю.

Ещё одно доказательство того, что я не прав! :man_shrugging:

Отлично!

Но discourse-setup предназначен только для тех, кто практически ничего не знает об администрировании систем. Если вы умеете устанавливать SMTP-сервер, вы сможете отредактировать YAML-файл.

Если у хоста, на котором запущен контейнер, есть имя, которое можно получить через DNS, достаточно указать его:

DISCOURSE_SMTP_ADDRESS: real.machine.example.com

Postfix по-прежнему будет видеть, что источник письма локальный, и обрабатывать его соответствующим образом.

Если DISCOURSE_HOSTNAME и DISCOURSE_SMTP_ADDRESS совпадают, вызовет ли это проблемы?

Я настроил Postfix и Dovecot на хосте Docker для принятия аутентифицированных запросов через TLS. У меня есть действительные сертификаты для моего сервера, но независимо от конфигурации, которую я пробую, я не могу заставить Discourse корректно отправлять письма на Postfix, работающий на хосте Docker.

Если я использую имя хоста (discourse.[myhost].com), это не работает (даже подключение не устанавливается). Если я использую IP-адрес хоста Docker (172.17.0.1), я получаю ошибку:

hostname "172.17.0.1" does not match the server certificate

Очевидно, мне нужно использовать полное доменное имя (FQDN), которое использовалось при создании сертификатов. Если я попробую установить DISCOURSE_SMTP_ENABLE_START_TLS в false, система сообщит, что необходимо выполнить команду START TLS. Я не хочу открывать Postfix без TLS, так что этот вариант для меня не подходит.

Использование внешнего SMTP-реле тоже невозможно, так как я не хочу платить больше только для того, чтобы письма не попадали в папки спам/мусор у получателей.

Честно говоря, у меня есть лишь поверхностное понимание сетевой модели Docker и ещё меньше — настройки SMTP-сервера Postfix с аутентификацией через Dovecot, но я не полный новичок. Однако настроить это безопасным и защищённым способом оказывается крайне сложно.

@maltfield Я читал вашу статью об Open Source Ecology, но я не хочу использовать неаутентифицированное соединение через порт 25. В университете, где я работаю, действуют очень строгие правила касательно использования незашифрованных и неаутентифицированных каналов связи (даже в рамках локальной сети, как в данном случае). Они слишком обеспокоены тем, что это может быть использовано недовольным студентом во вред.

Итак, я понял, что что-то неладно с использованием одного и того же имени хоста и для сервера Discourse, и для SMTP-сервера.

Дальнейшее расследование показало, что контейнер Docker добавляет в файл hosts следующую запись:

172.17.0.2	discourse.[mydomain].com discourse

Таким образом, любая попытка использовать одно и то же имя хоста для работающего контейнера и для хоста Docker приведёт к тому, что все запросы, исходящие из контейнера, будут направляться на сам контейнер, а не на хост Docker.

Какой же это провал! Почему Discourse не предоставляет SMTP-сервер по умолчанию в контейнере!?
Или хотя бы не упрощает использование Discourse без Docker!

Два дня моей жизни потеряны из-за этой проблемы.

В конечном итоге я принимаю тот факт, что не могу использовать TLS для связи с SMTP, запущенным на хосте Docker (без получения сертификатов с использованием другого имени хоста). Чтобы заставить это наконец работать, я должен был убедиться, что 172.17.0.0/16 добавлен в переменную mynetworks в файле main.cf Postfix:

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16

Это позволяет Postfix видеть любой контейнер Docker, запущенный на этом сервере, как часть сети.

Еще одно изменение, которое мне пришлось внести, — убедиться, что smtpd_sasl_security_options установлен в noanonymous, чтобы предотвратить использование Postfix в качестве SMTP-релея «чужаками». Убедитесь, что опция noplaintext не установлена здесь, иначе Postfix будет разрешать аутентификацию только через TLS.

smtpd_sasl_security_options = noanonymous

С этими настройками конфигурации я мог указать следующие параметры в app.yml:

  DISCOURSE_SMTP_ADDRESS: 172.17.0.1                            # IP-адрес хоста Docker (как виден изнутри этого контейнера)
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: discourse
  DISCOURSE_SMTP_PASSWORD: pa$$word
  DISCOURSE_SMTP_ENABLE_START_TLS: false           	             # (необязательно, по умолчанию true)
  DISCOURSE_SMTP_DOMAIN: discourse.[mydomian].com                # (требуется некоторыми провайдерами)
  DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.[mydomain].com # (адрес для отправки уведомлений)

Я также создал локальную учетную запись пользователя на хосте Docker исключительно для целей аутентификации SASL.
Благодаря этим изменениям я наконец смог отправлять письма из контейнера, но не могу не чувствовать, что это неоптимальная конфигурация. В идеале должно быть возможно использовать желаемое имя хоста для хоста Docker и направлять запросы к discourse.[mydomain].com в нужное место.

Теперь мне нужно настроить SPF и DKIM, чтобы письма попадали во входящие ящики пользователей (а не в папку спама). Я очень надеюсь, что когда-нибудь этот болезненный процесс станет более автоматизированным. Возможно, стоит предоставить инструкции по настройке Discourse без использования Docker (чтобы его можно было использовать, например, с cPanel) или сделать настройку почты менее болезненной, предоставив какую-либо конфигурацию SMTP по умолчанию прямо в контейнере Docker!

Если вернуться в начало 1990-х, всё было именно так, как вы хотите. Все описанные вами вещи просто работали. Но спамеры привели к тому, что всё стало гораздо сложнее. Процесс будет становиться только труднее, именно поэтому рекомендуется использовать какой-либо сервис, который берёт на себя многие из этих сложностей.

Рад, что у вас получилось настроить почту!

С момента публикации вчерашней версии руководства по устранению неполадок с электронной почтой внесены некоторые обновления. Если вы всё ещё не удовлетворены настройкой почты, попробуйте ещё раз!


Это можно решить, используя:


… это просто стандартное разрешение доменного имени в IP-адрес через DNS.

Не поймите меня неправильно. Я понимаю важность SPF и DKIM. Это просто раздражает. Я бы хотел, чтобы это можно было установить на наших текущих серверах cPanel, где подобные настройки уже выполнены.

Вот чего мне не хватало. Теперь всё работает с TLS.

У меня также настроен DKIM, так что письма больше не будут попадать в спам.