angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Отправка почты из Docker контейнера через ISPConfig3 хоста Postfix MTA

Используйте IP-адрес моста докер0 для подключения к сети Postfix

28 июня 2019
post main image
Original photo unsplash.com/@alejandroescamilla.

В бесконечном количестве проблем, с которыми вы сталкиваетесь и решаете, когда начинаете использовать новую технологию, я сталкиваюсь с новой: как отправлять электронную почту из моего приложения с помощью ISPConfig хоста (Mail Transfer Agent). Я нашел два способа сделать это:

  • Отправка почты из нашего контейнера на адрес хоста, на котором она прослушивается
  • Запишите почтовый файл в каталог на хосте и используйте скрипт для переноса почтовых файлов на сервер. MTA

Может быть, позже я расследую метод почтовых файлов, см. также ссылки ниже.

Отправка почты из нашего контейнера на адрес хоста, на котором она прослушивается

Для этого мы должны использовать Docker мост под названием docker0. Из Docker документов:

По умолчанию Docker сервер создает и настраивает сетевой интерфейс docker0 хост-системы под названием docker0, который представляет собой устройство моста Ethernet. Если при запуске контейнера не указать другую сеть, контейнер подключается к мосту, и весь поток, идущий от него и идущий через мост к контейнеру, направляется к контейнеру, Docker daemonкоторый обрабатывает маршрутизацию от имени контейнера.

Docker конфигурирует docker0 с IP-адресом netmaskи диапазоном назначения IP-адресов. Контейнерам, подключенным к мосту по умолчанию, присваиваются IP-адреса в этом диапазоне".

Это означает, что при использовании контейнера для проверки возможности подключения к тестовому письму MTA и отправки тестовых сообщений мы не можем этого сделать:

telnet localhost 25
telnet 127.0.0.1 25

но вместо этого должен использовать IP-адрес моста доккера:

telnet <docker0 IP address> 25

IP-адрес докера0 можно узнать, например, запустив его:

ifconfig docker0

Тестирование на локальной машине (Ubuntu 18.04 desktop)

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

  • Проверьте порты прослушивания и приложения на предмет . Запустите одну из них:
    sudo lsof -i -P -n | grep LISTEN | grep 25
    sudo netstat -tulpn | grep LISTEN | grep 25
  • Рабочий контейнер. Alpine Подходит для нашей цели. Введите его, запустив:
    docker run -it alpine /bin/sh
  • Telnet в Docker контейнере. Находясь в контейнере, выполните установку, выполнив пробежку:
    apk add busybox-extras
  • socket server Прослушивание port 25. Я использовал следующее:
    # description: python 3 socket server printing and echoing received data
    import socket
    import sys
    
    # host: all available interfaces
    host = ''
    # port: set to port 25 for our test
    port = 25
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print('socket created')
    try:
    	s.bind((host, port))
    except socket.error as msg:
    	print('bind failed, msg = {}'.format(msg))
    	sys.exit()
    print('bind done')
    
    s.listen(1)
    print('start listening')
    
    conn, addr = s.accept()
    print('Connection from ', addr)
    while True:
        data = conn.recv(1024)
        print('data = {}'.format(data))
        if not data: 
            break
        conn.sendall(data)
    conn.close()

На моей локальной машине IP-адрес моста докер0 будет следующим: 172.17.0.1.

Во-первых, мы проверяем, port 25 есть ли такая возможность (она должна быть):

sudo lsof -i -P -n | grep LISTEN | grep 25

Откройте другое окно терминала, запустите эхо-сигнал :

sudo python3 listen_port.py

Это печатает какой-то текст:

socket created
bind done
start listening

Теперь должны использоваться (нашими ):

python3    5857            root    3u  IPv4 2925123970      0t0  TCP *:25 (LISTEN)

Откройте другое окно терминала, запустите и введите Docker контейнер:

docker run -it  alpine /bin/sh

Запустите 'apk add busybox-extras' для установки .

В Docker контейнерном типе:

telnet 127.0.0.1 25

Вы получите сообщение:

telnet: can't connect to remote host (127.0.0.1): Connection refused

Теперь используйте вместо этого IP-адрес docker0:

telnet 172.17.0.1 25

В окнах терминала socket server вы должны увидеть сообщение:

Connection from  ('172.17.0.2', 38928)

В Docker контейнере введите несколько слов, нажмите Enter и т.д. Они должны быть отражены в Docker контейнере и вы должны увидеть их в окне socket server терминала.

Имейте в виду, что могут возникнуть проблемы с последовательностью операций. порядком запуска Docker контейнера socket server и его содержимого. Также при прерывании работы socket server и повторном запуске может появиться ошибка:

OSError: [Errno 98] Address already in use

В этом случае подождите некоторое время, прежде чем начинать заново.

Пока все в порядке. Мы можем общаться через докер0 мост. Давайте перейдем к производственному серверу.

Внедрение на производстве ("Debian Растягивание + ISPConfig3")

На моем производственном сервере IP-адрес моста docker0 равен: 172.17.0.1

Для ISPConfigтроих MTA это... Конфигурация находится в файле:

/etc/postfix/main.cf

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

inet_interfaces = all
...
mynetworks = 127.0.0.0/8 [::1]/128

Строка с символом ''inet_interfacesвыглядит хорошо, Postfix уже слушает все интерфейсы, нет необходимости менять эту строку. Строка с " 'mynetworksдолжна быть изменена, она должна включать в себя:

  • IP-адрес моста докер0 и..,
  • IP-адреса Docker изображений (которые будут отправлять почту)

У нас уже есть IP-адрес моста docker0, 172.17.0.1. Чтобы найти IP-адреса наших контейнеров, мы можем сначала проверить их:

docker ps

чтобы получить идентификатор контейнера, а затем использовать инспекцию, например

docker inspect c2c44e9bea28

Это даст много информации и где-то в конце концов, что-то вроде:

"IPAddress": "172.20.0.2"

Чтобы включить все Docker адреса, я использую подсеть 172.16.0.0/12, это дает диапазон IP-адресов: 172.16.0.1 - 172.31.255.254. Тогда mynetworks линия становится:

mynetworks = 127.0.0.0/8 [::1]/128  172.16.0.0/12

После изменения этой строки в файле /etc/postfix/main.cf и сохранения файла мы должны перезапустить :

service postfix restart

Чтобы проверить, работают ли наши изменения, мы снова используем . По типу хоста:

telnet 127.0.0.1 25

Он напечатает что-то вроде:

220 server.example.com ESMTP Postfix (Debian/GNU)

Запомни эту строчку! Введите quit, чтобы остановиться. Теперь мы начинаем маленький Docker контейнер, как на локальной машине:

docker run -it  alpine /bin/sh

и снова добавить, запустив 'apk add busybox-extras'. Конечно:

telnet 127.0.0.1 25

потерпит неудачу:

telnet: can't connect to remote host (127.0.0.1): Connection refused

Но

telnet 172.17.0.1 25

теперь должен дать вам сообщение того же самого сообщения MTA, что и на хосте:

220 server.example.com ESMTP Postfix (Debian/GNU)

В качестве заключительного теста, мы можем отправить письмо себе из контейнера, используя . Получить sendmail варианты:

sendmail --help

Где-то здесь есть черта:

-S HOST[:PORT]	Server (default $SMTPHOST or 127.0.0.1)

Это означает, что мы можем изменить адрес по умолчанию на адрес докер0. Чтобы отправить почту, напечатайте:

sendmail -S 172.17.0.1 yourname@yourdomain.yourextension

Начинай печатать:

To: someone@example.com
Subject: My docker test mail

Hello this is a mail from my docker container. 
Thank you.

Введите Ctrl-D, чтобы отправить письмо. Вы можете просмотреть /var/log/mail.log для вашего почтового сообщения. Да, и, к сожалению, возникла ошибка, сообщение в mail.log:

You cannot send mail from 4449d8888ddd since that domain cannot receive mail

Далее проверка показала, что домен from не является полностью квалифицированным доменом. Вы можете проверить это, выполнив команду Verbose (-v). Оно показало:

sendmail: send:'MAIL FROM:<root@1f12e2cef814>'

Решение заключается в добавлении опции MAIL FROM SENDER (-f) в командную строку:

sendmail -v -S 172.17.0.1 -f info@example.com yourname@yourdomain.yourextension

Начни снова печатать:

To: yourname@yourdomain.yourextension
From: someone@example.com
Subject: My docker test mail

Hello this is a mail from my docker container. 
Thank you.

Введите Ctrl-D, чтобы отправить почту. Теперь почта отправлена и должна появиться в вашем почтовом ящике (или спаме). Миссия выполнена!

Использование локального сервера для отладки

Существует Python один лайнер, который действует как SMPT сервер и может быть полезен для отладки, флаг -d добавляет отладочную информацию:

sudo python -m smtpd -d -n -c  DebuggingServer 172.17.0.1:1025

Заключительные замечания

Возникает проблема с описанным методом, и это, в том числе, ссылки:

Postfix должен быть запущен после того, как будет поднят интерфейс docker0".

Потому что Docker сетевой мост может быть еще не готов к постфиксу загрузки системы, но может не запуститься, потому что он не может быть привязан к этому адресу.

Я еще не искал решения, но это страшно. Если сервер перезагружен, я не должен забывать проверить, можно ли отправлять почту. По этой причине метод 'mail files' может быть лучшим решением, так как нет зависимости от docker0 bridge.

Ссылки / кредиты

Configure sendmail inside a docker container
https://stackoverflow.com/questions/26215021/configure-sendmail-inside-a-docker-container

Send an email from a Docker container through an external MTA with ssmtp
https://www.michelebologna.net/2019/send-an-email-from-a-docker-container/

Sending email from docker through Postfix installed on the host
http://satishgandham.com/2016/12/sending-email-from-docker-through-postfix-installed-on-the-host/

Sending email inside a docker container to hosts smtp running postfix
https://serverfault.com/questions/817353/sending-email-inside-a-docker-container-to-hosts-smtp-running-postfix

Using system postfix as mail relay for docker containers
https://markusbenning.de/blog/2017/08/16/using-system-postfix-as-mail-relay-for-docker-containers.html

Оставить комментарий

Комментируйте анонимно или войдите в систему, чтобы прокомментировать.

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.