SASL, 587번, 25번 포트
SASL 정의
- 프로토콜과 인증 매커니즘의 분리를 도움
- 만약 기존의 프로토콜 내에 인증 방식이 존재했다면, 새로운 인증을 추가하거나 기존의 인증을 변형할 때마다 프로토콜 자체를 수정해야 함
- SASL을 사용하면 SASL 추상화 계층이라는 것이 제공되어 해당 계층을 통해 프로토콜과 인증 방식을 연결해줌
- 프로토콜과 인증 방식이 분리되어 결합도가 낮아지고, 각각을 독자적으로 사용할 수 있게 됨
- 클라이언트의 신원을 확인 가능
- SASL은 인증 신원, 인가 신원의 2가지 신원을 가짐
- 클라이언트는 SASL을 통해 자신의 신원을 서버에 제시해 인증받음
- 간단한 보안 계층을 제공
- 보안 계층은 클라이언트와 서버 간 협상을 통해 결정 가능
- 이는 SASL 대신 TLS로 대체 가능
- 보안 계층을 사용하지 않을 수도 있음
SASL이란
- 추상화 계층 프레임워크
- 애플리케이션 프로토콜과 다양한 인증 매커니즘을 연결
- 클라이언트의 신원(인증, 인가)을 안전하게 인증
- 필요한 경우 보안 계층을 협상
Postfix의 SASL
클라이언트-서버
- 클라이언트
- SMTP 관련 API를 사용해 SMTP 통신을 시작
- SMTP 서버와 연결되어 메일 발송, 릴레이, 수신 등을 요청하는 주체
- 서버
- SMTP 통신 요청을 받아 응답 및 처리를 진행하는 주체
- 메일을 실제로 발송, 릴레이, 수신
- 서버는 클라이언트의 요청을 받기 전 SASL을 통해 해당 클라이언트가 누구인지(인증), 해당 클라이언트가 행위에 대한 권한을 갖는지(인가) 신원을 검증할 수 있음
- 서버는 클라이언트를 어떤 인증 매커니즘으로 검증할 지 선택할 수 있음
사용 가능한 SASL
- Cyrus
- Dovecot → 이 프로젝트에서는 Dovecot-core를 사용해 SASL을 구축
분산 이메일 시스템과 SASL
- 포트 사용
- 587번 포트는 SASL을 의무적으로 사용, TLS 인증이 권장(RFC 6409)
- GCP 정책으로 25번 포트의 외부 연결이 차단되어 587번 포트를 사용해야 해야 함, 내부 연결은 상관 없음
- 모든 SMTP 서버-클라이언트 간의 연결에 있어 반드시 587 포트를 쓸 필요는 없음
- 즉, 모든 SMTP 서버-클라이언트 간의 연결에 있어 SASL을 쓸 필요가 없다는 뜻
- 587번 외에도 465번 포트, 2525번 포트를 쓰기도 하지만 587번이 가장 권장
- 465는 공식적으로 사용이 권장되지 않는(deprecated) 포트
- 2525는 모든 포트(25, 587)가 막혔을 때 대체로 사용하는 포트
- 현재 설계한 시스템의 구조는 다음과 같음(GCP 사용)
- 웹 서버(MUA) → 아웃바운드 SMTP(MTA) → 방화벽 SMTP(MTA) → 인터넷 환경 → 방화벽 SMTP(MTA) → 인바운드 SMTP(MTA) → MDA + DB
- →를 기준으로 SMTP 클라이언트 → SMTP 서버가 됨
- 여기서 웹 서버 → 아웃바운드, 방화벽 → 인터넷에만 587번 포트를 사용, 나머지는 25번 포트를 사용
- 웹 서버 → 아웃바운드는 사용자가 메일 서버에 메일을 제출하는 구간으로 SASL을 통해 사용자를 인증, 587번 포트를 쓰는게 올바름
- 방화벽 → 인터넷은 GCP 정책으로 25번 포트가 막혀 587번 포트를 쓰려고 생각(해당 생각이 잘못되었음을 아래에서 서술)
587번 포트 사용?
- 587번 포트를 쓰려면 SASL을 의무적으로 적용해야 할 텐데, 불특정 다수의 MTA와 어떻게 SASL이 가능한지 의문이 생김
- 웹서버 → 아웃바운드 SMTP는 SASL을 통한 인증이 충분히 가능해보이지만, 방화벽 SMTP → 인터넷 환경은 불가능해보인다는 생각도 듦
- 인터넷 환경으로 메시지가 나가는 순간부터 어떤 MTA로 메시지가 전송될지 예측할 수 없음
- 어떤 MTA로 메시지가 전송될 지 모르기 때문에 MTA간 서로 신원을 모를텐데 인증을 어떻게 할 수 있는지 의문
- 과연 여기서 587번 포트의 사용이 정당한지 확인해보기로 함
MSA(Message Submission Agent): RFC 6409
- SMTP는 메시지 전송(transfer) 프로토콜로 정의
- 완성된 메시지를 라우팅, 전달
- 메시지 텍스트를 변형하지 않음
- 현재에는 SMTP가 메시지 제출(submission) 프로토콜로도 널리 사용
도입 배경
- 보안 중요성 증대
- 초기 메시지 제출 시 인증 및 권한 부여의 중요성 증가
- 많은 사이트들이 25번 포트의 아웃바운드 트래픽 금지
- 메시지 불완전성
- 제출되는 메시지가 완성된 상태가 아닐 수 있음
- 메시지를 표준에 맞게 보완할 필요가 있음
- 사이트 정책 준수
- 사이트의 정책에 따라 메시지 텍스트를 검사하거나 수정해야할 수 있음
- 이는 초기 제출 MTA가 아닌 다른 MTA가 수행할 경우 문제가 발생할 수 있음
- 이는 표준화된 MTA 기능의 영역을 벗어나는 것으로 간주
제출과 전송의 분리
- 메시지 제출(submission)과 메시지 전송(transfer)을 분리
- MUA로부터 메시지 제출을 받는 프로세스를 MSA(Message Submission Agent)라고 정의, MTA에게 메시지를 전달하는 SMTP 클라이언트로 역할
- 587번 포트는 메시지 제출을 위해 특별히 예약된 포트
GCP의 25번 포트
- 현재 GCP VM에서 분산 이메일 시스템을 구축
- GCP는 기본적으로 25번 포트(SMTP transfer)의 아웃바운드 트래픽을 차단하기 때문에 587번 포트(SMTP submisson)를 사용
- 587번 포트는 SASL 사용이 의무
- 그렇다면 내 아웃바운트 MTA(GCP 내 VM에 위치)는 불특정 다수의 수신 MTA에게 메일을 보낼 때 어떻게 해야 하는지?
587번 포트는 25번 포트의 대안이 아님
- 25번 포트는 기본적으로 MTA에서 다른 MTA로 메일을 전송하는 포트, 불특정 다수의 MTA에게 메일을 보내거나 받을 때 사용하는 포트
- 587번 포트는 SMTP submission 포트, 즉 메일 '제출용' 포트
- MUA에서 MSA로 메일을 제출하기 위한 포트이지, MTA에서 다른 MTA로 메일을 전송하기 위한 포트가 아님
- 587번 포트는 메일 발송용이 아니기 때문에 25번 포트의 대안으로 사용해선 안됨
25번 포트 우회
- 결국 메일을 전송하기 위해서는 반드시 25번 포트를 거쳐야 하는 상황
- 하지만 GCP에서는 25번 포트가 막혀있기 때문에 다음과 같은 방법을 통해 해결 가능
- 온프렘, 다른 클라우드 서비스의 vm을 통해 25번 포트 사용
- VPC 서비스가 아닌 tailscale을 통해 네트워크 구축 및 방화벽 설정 필요
- 프로젝트 범위를 좀 벗어나는 것 같다는 생각이 듦
- GCP에서 25번 포트 개방
- GCP SMTP Relay 사용
- google workspace 유료 계정 필요(14일 무료체험 가능하긴 함)
- 구글이 운영하는 중계 smtp 서비스를 거쳐 메일을 전송
- 최종 메시지 발송이 구글의 인프라(IP 평판, 인증)를 거쳐 전송
- 아웃바운드 MTA는 구글에게 맡기고, 나는 MSA만 개발하는 셈
- 서드파티 SMTP 서비스를 쓰는 것과 유사
- 서드파티 SMTP 서비스 사용
- 아웃바운드, 방화벽 smtp 서버를 굳이 설정할 이유가 없이 서드파티 서비스 하나만 사용하면 됨
- 프로젝트의 목적을 해친다고 판단(사실상 "API 호출형 이메일 서비스 사용"에 가까움)
온프렘 사용하기
- 메일 송수신 시나리오
- 아웃바운드: 웹 서버(MUA) → 아웃바운드 SMTP(GCP) → 방화벽 SMTP(온프렘) → 인터넷 환경
- 인바운드: 인터넷 환경 → 방화벽 SMTP(GCP) → 인바운드 SMTP(GCP) → MDA + DB
- 설정
- 아웃바운드 시나리오의 방화벽 MTA는 온프렘으로, 인바운드 시나리오의 방화벽 MTA는 GCP VM으로 생성
- GCP는 25번 포트의 아웃바운드 트래픽은 막았지만, 인바운드 트래픽은 막지 않았음
- 온프렘과 GCP VM은 tailscale을 통해 하나의 네트워크로 묶음
- 온프렘은 오직 아웃바운드 SMTP MTA를 통해서만 트래픽을 받도록 설정, 다른 서버나 도메인의 릴레이는 모두 거부
- 단점
- 가정용 IP가 노출되어 평판이 낮아질 수 있음
- 분산 아키텍처의 관리 지점이 증가(온프렘, 클라우드)
- 네트워크 관리가 복잡해짐(VPC + tailscale)
- 프로젝트 주제 범위를 벗어남
서드파티 서비스 사용하기
- 메일 송수신 시나리오
- 아웃바운드: 웹 서버(MUA) → 아웃바운드 SMTP(GCP) → 서드파티 SMTP 서비스(외부 전송용) / 방화벽 SMTP(내부 전송용) → 인터넷 환경
- 인바운드: 인터넷 환경 → 방화벽 SMTP(GCP) → 인바운드 SMTP(GCP) → MDA + DB
- 설정
- 아웃바운드 시나리오에서 외부 메일 전송은 서드파티를 통해, 내부 전송은 Postfix를 통해 진행
- 단점
- 프로젝트의 목적을 해칠 수 있음 → 내부 전송용을 별도로 구현함으로써 조금 해소하고자 함
다른 VPS 사용
- 설정
- 단점
- tailscale을 통해 네트워크를 묶고 별도로 관리해야 함(온프렘과 유사하게 관리)
- 온프렘과 달리 가정용 IP의 평판 문제가 해소되고, 관리가 좀 더 편함
- 온프렘과 마찬가지로 관리 지점이 증가
결론
- 가능하다면 25번 포트가 개방된 VPS를 찾아 사용하는 것이 가장 좋아보임
- 단, 시간이 너무 부족하거나 VPS를 찾기 어렵다면 서드파티 서비스를 사용할 예정