SASL부터 GCP 25번 포트 우회까지

민정·2025년 8월 26일

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 사용

  • 설정
    • 25번 포트가 개방된 VPS를 찾아 사용
  • 단점
    • tailscale을 통해 네트워크를 묶고 별도로 관리해야 함(온프렘과 유사하게 관리)
      • 온프렘과 달리 가정용 IP의 평판 문제가 해소되고, 관리가 좀 더 편함
    • 온프렘과 마찬가지로 관리 지점이 증가

결론

  • 가능하다면 25번 포트가 개방된 VPS를 찾아 사용하는 것이 가장 좋아보임
  • 단, 시간이 너무 부족하거나 VPS를 찾기 어렵다면 서드파티 서비스를 사용할 예정
profile
시스템 + 리눅스 + 클라우드

0개의 댓글