Protonmail Bridge를 Discourse와 함께 사용

문제: a) Protonmail Bridge가 127.0.0.1 이외의 IP를 리스닝할 수 없고, b) Docker 컨테이너 내의 Discourse가 호스트 머신의 127.0.0.1으로 SMTP 요청을 보낼 수 없습니다.

해결 방법: 172.17.0.1(호스트 머신의 Docker 브리지 IP)로 전송하도록 구성한 후, Protonmail Bridge가 리스닝 중인 127.0.0.1으로 리디렉션합니다.

이를 위해 Socat을 사용합니다.

방법

Socat을 설치하는 것으로 시작합니다:
apt install socat

Socat을 서비스로 실행할 것입니다. 서비스 파일을 생성합니다:
nano /etc/systemd/system/protonsocat.service

… 그리고 다음 내용을 파일에 넣습니다:

[Unit]
Description=Socat Bridge ProtonMail/Discourse
After=protonbridge.service,docker.service
ReloadPropagatedFrom=docker.service

[Service]
ExecStart=socat -d -d -lm TCP4-LISTEN:1026,fork,reuseaddr,so-bindtodevice=docker0,range=172.17.0.0/24 TCP4:127.0.0.1:1025
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target

참고:

  • Socat이 모든 IP 172.17.0.0/24, 포트 1026을 리스닝하고, 트래픽을 Protonmail Bridge가 리스닝 중인 127.0.0.1:1025로 리디렉션하도록 구성했습니다.

  • Socat 문서의 예제: socat

  • -d -d 옵션은 fatal, error, warning, notice 메시지를 출력합니다. 로그에 이 정도 수준의 상세 정보가 필요하지 않을 수 있습니다.

다음으로, 서비스를 시작합니다:
systemctl start protonsocat

실행 중인지 확인합니다:
systemctl status protonsocat

부팅 시 자동으로 시작되도록 설정합니다:
systemctl enable protonsocat

완료! 이제 Discourse의 app.yml을 구성하고 재빌드합니다:

  DISCOURSE_SMTP_ADDRESS: 172.17.0.1
  DISCOURSE_SMTP_PORT: 1026
  DISCOURSE_SMTP_USER_NAME: <Proton Bridge 명령줄 애플리케이션에서 제공한 SMTP 사용자 이름>
  DISCOURSE_SMTP_PASSWORD: "<SMTP 비밀번호 - 따옴표로 감싸기>"
  DISCOURSE_SMTP_ENABLE_START_TLS: true
  DISCOURSE_SMTP_DOMAIN: <도메인 이름>
  DISCOURSE_NOTIFICATION_EMAIL: <Discourse가 트랜잭션 이메일을 보내는 주소>
2개의 좋아요

안녕하세요 @meggio
protonbridge.service를 찾을 수 없어서 protonmail.service로 대체했습니다.
하지만 After=protonbridge.service,docker.service 형식 관련해서 문제가 있는 것 같습니다.

@meglio 님, 안녕하세요. 이 부분이 오류를 일으키는 것 같습니다.

초기 sysctl 명령 실행 후

root@ip-172-31-0-166:/var/discourse# systemctl status protonsocat.service
● protonsocat.service - Socat Bridge ProtonMail/Discourse
     Loaded: loaded (/etc/systemd/system/protonsocat.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-12-18 20:58:18 UTC; 25s ago
   Main PID: 2020962 (socat)
      Tasks: 1 (limit: 1143)
     Memory: 2.0M
        CPU: 4ms
     CGroup: /system.slice/protonsocat.service
             └─2020962 socat -d -d -lm TCP4-LISTEN:1026,fork,reuseaddr,so-bindtodevice=docker0,range=172.17.0.0/24 TCP4:127.0.0.1:1025

Dec 18 20:58:18 ip-172-31-0-166 systemd[1]: Started Socat Bridge ProtonMail/Discourse.
Dec 18 20:58:18 ip-172-31-0-166 socat[2020962]: 2022/12/18 20:58:18 socat[2020962] W ioctl(5, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ...): Inappropriate ioctl for device
Dec 18 20:58:18 ip-172-31-0-166 socat[2020962]: N listening on AF=2 0.0.0.0:1026
**Dec 18 20:58:42 ip-172-31-0-166 systemd[1]: /etc/systemd/system/protonsocat.service:3: Failed to add dependency on protonbridge.service,docker.service, ignoring: Invalid argument**

또한 ./discourse-doctor를 실행할 때 다음과 같은 오류가 발생합니다.


==================== MAIL TEST ====================
For a robust test, get an address from http://www.mail-tester.com/
Or just send a test message to yourself.
Email address for mail test? ('n' to skip) [[REDACTED]@proton.me]: 
Sending mail to [REDACTED]@proton.me. . . 
SAM: sudo docker exec -w /var/www/discourse -i app rake emails:test[[REDACTED]@proton.me]
Testing sending to [REDACTED]@proton.me using 172.17.0.1:1026, username:[REDACTED]@proton.me with plain auth.
======================================== ERROR ========================================
                                    UNEXPECTED ERROR

**end of file reached**

====================================== SOLUTION =======================================
This is not a common error. No recommended solution exists!

Please report the exact error message above to https://meta.discourse.org/
(And a solution, if you find one!)

어떤 힌트나 조언이 있다면 감사하겠습니다. 도움이 될 것입니다!
감사합니다.

그 이후로 그 문제들을 해결하셨나요?

사실 더 심각한 문제가 있습니다. socat은 정상적으로 실행되고 있지만, telnet 172.17.0.1 1026 또는 172.17.0.2 1026에도 연결할 수 없습니다. 또한 127.0.0.1 1026과 1025도 시도해 보았지만, Discourse가 설치된 Docker 컨테이너 내부에서 모두 실패했습니다.

호스트 머신에서는 127.0.0.1 1025로 telnet을 통해 정상적으로 연결할 수 있습니다. Discourse에서 무언가를 변경한 건가요?

root@raspberry:/var/discourse# sudo systemctl status protonsocat.service 
● protonsocat.service - Socat Bridge ProtonMail/Discourse
     Loaded: loaded (/etc/systemd/system/protonsocat.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2023-02-25 20:37:34 CET; 4min 37s ago
   Main PID: 1530542 (socat)
      Tasks: 1 (limit: 9236)
     Memory: 816.0K
        CPU: 10ms
     CGroup: /system.slice/protonsocat.service
             └─1530542 socat -d -d -lm TCP4-LISTEN:1026,fork,reuseaddr,so-bindtodevice=docker0,range=172.17.0.0/24 TCP4:127.0.0.1:1025

Feb 25 20:37:34 raspberry.local systemd[1]: Started Socat Bridge ProtonMail/Discourse.
Feb 25 20:37:34 raspberry.local socat[1530542]: 2023/02/25 20:37:34 socat[1530542] W ioctl(5, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ...): Inappropriate ioctl for device
Feb 25 20:37:34 raspberry.local socat[1530542]: N listening on AF=2 0.0.0.0:1026

호스트 머신:

root@raspberry:/var/discourse# telnet 127.0.0.1 1025
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 127.0.0.1 ESMTP Service Ready
root@raspberry:/var/discourse# nmap 127.0.0.1 1025
Starting Nmap 7.80 ( https://nmap.org ) at 2023-02-25 21:03 CET
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000045s latency).
Not shown: 993 closed ports
PORT     STATE SERVICE
80/tcp   open  http
443/tcp  open  https
1025/tcp open  NFS-or-IIS
3306/tcp open  mysql
5432/tcp open  postgresql
8080/tcp open  http-proxy
8088/tcp open  radan-http

Nmap done: 2 IP addresses (1 host up) scanned in 3.36 seconds

호스트의 인터페이스:

root@raspberry:/var/discourse# ifconfig
br-eb8fd6a0d930: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:bdff:fe5c:8dbf  prefixlen 64  scopeid 0x20<link>
        ether 02:42:bd:5c:8d:bf  txqueuelen 0  (Ethernet)
        RX packets 1336  bytes 94913 (94.9 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2254  bytes 3098019 (3.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:60ff:feaf:784c  prefixlen 64  scopeid 0x20<link>
        ether 02:42:60:af:78:4c  txqueuelen 0  (Ethernet)
        RX packets 295920  bytes 21547471 (21.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1049936  bytes 1487623390 (1.4 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether dc:a6:32:c2:70:f8  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 97179  bytes 22606251 (22.6 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 97179  bytes 22606251 (22.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth5a26573: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::428:bfff:febf:cf5c  prefixlen 64  scopeid 0x20<link>
        ether 06:28:bf:bf:cf:5c  txqueuelen 0  (Ethernet)
        RX packets 1336  bytes 113617 (113.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2279  bytes 3099825 (3.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethe0f8588: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::a04d:adff:feb1:351a  prefixlen 64  scopeid 0x20<link>
        ether a2:4d:ad:b1:35:1a  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 32  bytes 2488 (2.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethfe706a1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::74b3:3aff:feea:89ec  prefixlen 64  scopeid 0x20<link>
        ether 76:b3:3a:ea:89:ec  txqueuelen 0  (Ethernet)
        RX packets 4459  bytes 287499 (287.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5221  bytes 7330834 (7.3 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.4  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::dea6:32ff:fec2:70f9  prefixlen 64  scopeid 0x20<link>
        ether dc:a6:32:c2:70:f9  txqueuelen 1000  (Ethernet)
        RX packets 2789702  bytes 3447696344 (3.4 GB)
        RX errors 0  dropped 7  overruns 0  frame 0
        TX packets 1082661  bytes 213831559 (213.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Docker

root@raspberry-app:/var/www/discourse# telnet 172.17.0.1 1026
Trying 172.17.0.1...
telnet: Unable to connect to remote host: Connection refused