Linux, Server, Web

AWS SES + Postfix + Dovecot 메일 서버 구축하기

iolate 2021. 8. 12. 13:40

(작성 중...)

보통 메일 서버를 직접 구축하는 짓은 하지 말라고들 한다.
스팸/바이러스 메일을 걸러내는 작업, 내 메일이 스팸처리가 되지 않게 하기 위한 작업, 메일을 중단 없이 수신할 수 있도록 지원 등등...
물론 직접 구축하는 작업이 아무나 할 수 있는게 아니기도 하고.

그래서 개인 도메인을 이용한 메일을 사용하기 위해선 유/무료의 기업용 서비스를 이용하거나 메일건 같은 서비스를 이용한다.
무료는 거의 없어지는 추세에 다음 스마트워크나 메일건 정도 남아있지만 제약들이 좀 불편했고, 유료도 서비스 자체나 과금 정책 등도 마음에 안드는 구석들이 하나씩 있어서 어떻게 하면 좋을까 고민하던 중, 어느정도 손이 가지만 타협할만한 방법이 있는 것 같아서 사용 및 설정을 해보았다.

일반 메일 서버 구축을 하듯이 Postfix + Dovecot 을 설정하지만, 실제 외부와 통신은 AWS SES를 거쳐서 진행하는 방식으로 구성을 하였다.
참고로 이미 이런 형태로 제공하는 가이드 등이 존재하지만, 다양한 계정으로의 수신을 지원하지 않아서 그 부분 등을 고려하여 세팅을 진행하였다.


AWS SES

AWS Simple Email Service 라고, 메일의 송수신을 지원하는 서비스이다.
다만 일반적인 메일 서비스처럼 지원을 하는건 아니고 송/수신이 조금씩 다르다.

일반적인 메일 서비스처럼 바로 사용할 수 있는건 아니지만(그런 목적으론 유료의 AWS WorkMail이 있다)
송신 기준으로 메일 전송에 필요한 각종 서버 설정을 하지 않고 AWS의 신뢰도에 기댈 수 있고, 수신 기준으로도 AWS가 일단 안정적으로 받아주고 시작하는게 좋아보여서 사용하기로 하였다. (바이러스 검사나 스팸 체크도 해주지만 내가 후처리를 따로 해줘야 한다.)

사용 방식 / 비용

먼저 송신은 초당, 일당 전송 제한이 있으며
AWS API를 이용하여 전송(월 62,000건 무료 후 과금)을 하거나, AWS IAM 사용자를 이용한 SMTP로 전송이 가능하며,
1000건당 $0.1 및 용량 기준으로 GB당 $0.12 가 과급된다.

후자의 SMTP 방식을 이용하면 일반 메일 클라이언트에 등록해서 사용할 수 있긴 한데, IAM을 사용하기 때문에 사용자 아이디/비밀번호를 내가 설정할 수도 없고 권한 부여도 까다롭다.

수신은 정한 규칙에 따라 AWS 람다를 실행하거나, S3에 저장하거나, SNS 토픽을 발행하는 등의 방식으로 이루어진다.
이 또한 1000건당 $0.1 (1000건 무로) / 256KB 1 chunk 기준으로 chunk 1000건당 $0.09 과금된다.
작성일 기준으로 한국 리전은 수신을 지원하지 않아 us-east-1 에서 사용하였음.

AWS SES 설정

AWS 에서 메일 송신을 위해선
1. 도메인 혹은 메일 주소 인증
2. 도메인의 경우 DKIM 등 설정
3. 외부로 메일 전송을 위한 Sandbox 해제 요청
작업을 해야하고,

수신을 위해선 MX레코드 설정이 필요하다.
이런 부분은 다른 사람들이 쓴 글이나 AWS 가이드에도 설명이 잘 되어있으니 생략.

이 후 Rule set 설정, Lambda, S3, SNS 등 설정은 분량 관계상 별도 포스팅으로. (작성 후 링크 예정)


Postfix

SMTP 프로토콜을 이용하여 메일을 수발신 할때 사용하는 프로그램. MTA (Mail Transfer Agent) 의 한 종류이다.
예전엔 sendmail 이 사용되었으나 요즘엔 Postfix를 가장 많이 사용한다.

Postfix 기능들

이 프로그램이 하는 역할이 겉으로 보기엔 단순 메일 수발신이지만 자세히 보면 좀 다양하다. 적절히 필요한 것만 취하면 됨.

1. 서버 내에서 내/외부로 메일 전송시 처리
    -> 안 써서 필요없음

2. 외부 클라이언트에서 서버를 통하여 메일 전송 (SMTP Submission)
    -> AWS의 SMTP를 사용해도 되는데, 메일 주소(사용자)별 인증을 쓰고 싶어서 이용.

3. 외부 클라이언트로 전송할때 사용자 인증 / 메일 검증 등
    -> 인증은 Postfix 자체적으로 할 수 있게 설정도 가능한데, 후술할 Dovecot과 연결하여 Dovecot의 인증을 사용하는 방법도 가능하다. 다 따로 구현하면 관리가 번거로워지니 이 방법을 사용할 예정.

4. 내 도메인으로 전송된 메일을 수신
    -> 나의 경우 수신을 AWS가 해주기 때문에 불필요한 기능이지만, 발송 과정에서 Postfix를 사용하고 있고 내 도메인으로 전송하는 경우가 발생할 수 있기 때문에 적절한 설정을 해줘야한다. (예시로 a@naver.com 에서 b@naver.com 으로 메일을 보내는 경우.)
        기본적으론 서버 내 해당하는 경로에 메일 원문을 저장하게 되어 있지만, 난 Dovecot 으로 전송하도록 설정할 예정

5. 메일 수신시 사용자 존재 여부 확인 / alias (다른 주소로 수신하는 기능)
    -> 메일 수신자에 따라 실질적으로 어떤 계정이 해당 메일을 받을지 결정하는 기능..
        support@도메인 으로 전송하면 CS팀에 속한 직원이 모두 해당 메일을 받는다거나.. 하는 목적으로 사용된다.
        난 내 도메인으로 오는 전체 메일을 내가 사용할 한두개 계정으로 받기 위해 사용할건데, 메일 수신을 Postfix만 하는게 아니라서 Postfix 와 Lambda 양쪽에 동일하게 작동하도록 구성해주어야 한다.

6. 다른 서버가 전송하는 메일을 다른 서버로 릴레이
    -> 보안 상의 이유 등으로 보통 비활성화

 

Postfix 설정

분량 관계상 포스팅을 분리하여 작성 (작성 후 링크 예정)


Dovecot

메일 박스를 관리하며 POP3, IMAP 등 프로토콜을 지원하여 다른 프로그램에서 메일을 받아갈 수 있도록 지원한다.
SMTP Submission 기능도 지원하는 것 같긴 하던데, 어차피 Postfix도 필요할 것 같아서 사용하지 않았음.

MTA(Postfix)가 메일을 수신해서 폴더에 저장하면 Dovecot이 알아서 그걸 읽는 방법도 있고,
MTA가 다시 Dovecot으로 LDA(Local Delivery Agent)나 LMTP(SMTP 개량 프로토콜)를 통해 보내줄 수도 있다.
예전엔 LDA를 썼었는데 최근엔 설정 편의성과 성능 때문에 LMTP를 더 많이 쓴다고 한다.

나의 경우 역시 Postfix - LMTP -> Dovecot 로 설정을 하였고,
AWS SES에서 수신한 메일도 AWS SES -> S3 -> SNS -> Lambda - LMTP -> Dovecot 으로 구성을 하였다.
보통 Lambda에서 Dovecot의 메일박스로 파일을 바로 전송시키는 방법을 사용하는데, 이러면 폴더 구조 같은걸 내가 신경 써줘야해서 난 수신자/alias 구분만 Lambda에서 하고 LMTP로 Dovecot에 떠넘겼음.

Dovecot 설정

역시 분량 관계상 포스팅 분리하여 작성 (작성 후 링크 예정)


사용 포트 / TLS

Dovecot 에서 사용할 POP3 와 IMAP 은 TLS 암호화가 추가된 버전인 POP3S(995/tcp), IMAPS(993/tcp) 만 사용할 예정이다.
내부 메일 전달을 위한 LMTP는 Postfix만 쓸거면 unix socket으로 해도 되지만, Lambda에서 사용해야 하니 적당히 임의로 2525/tcp 포트도 추가로 사용.

사용자가 메일 전송을 위해 Postfix에 접속할 때는 SMTPS(tcp/465) 대신 SMTP + STARTTLS 을 사용할거고, 25/tcp 가 OUTBOUND로 차단되는 경우가 많기 때문에, 587/tcp 포트를 사용한다.

즉 587, 993, 995 3개 포트는 모두 열려있어야 하며, 2525 포트는 내부에서 사용할 수 있게만 열려있으면 된다.

TLS 연결을 위해 인증서를 발급받아야 하는데, Let's encrypt(certbot) 을 이용한 웹서버용 인증서를 그대로 사용할 수 있다.
이 인증서의 발급 방법은 생략.
발급된 경로만 잘 확인하여 후에 설정할 때 적절한 경로를 넣어주면 된다.

이 후 발급된 인증서를 Dovecot / Postfix 각각 설정에 적절히 넣어주면 된다.


전체 구성도

아직 시작도 안했지만 벌써부터 복잡한, 전체 구성도는 아래와 같다.

DB와 메일 서버는 동일 서버여도 되지만 난 분리되어 있기 때문에 이미지상 분리해뒀다.

이미지에서 볼 수 있다시피 Lambda가 DB와 EC2 서버에 각각 접근해야 하는데, DB는 당연하고 LMTP도 Public 오픈을 권장하지 않기 때문에 Lambda를 private subnet에 넣고 동일 VPC 네트워크 내에 사설망을 이용하도록 구성하였음.


나중에 사용자 인증을 LDAP 으로 사용한다거나.. 등도 고민 중인데..... 갈길이 멀다.....ㅠ