SMTP relay는 2026년에 실제로 어떻게 작동하는가

1982년엔 모든 메일 서버가 아무한테나 relay해줬다 — 그게 설계였다. 지금은 모르는 사람한테 relay해주면 점심도 되기 전에 블록리스트에 오른다. 'relay'라는 단어는 살아남았고, 그 아래 모든 게 뒤집혔다.

1982년엔 내 메일 서버가 생판 모르는 남을 위해 메일을 relay해줬다. 버그가 아니라 그게 핵심이었다. RFC 821은 어떤 호스트든 다른 호스트로 갈 메시지를 받아서 신뢰만으로, 아무것도 묻지 않고 넘겨주는 네트워크를 묘사했다. 그게 SMTP였다. 이름에 박힌 “relay”는 켜고 끄는 기능이 아니라 프로토콜 그 자체였다.

지금 그렇게 했다간 점심도 되기 전에 블록리스트 열 개에 오른다. open relay — 아무한테서나, 아무한테로나 메일을 받아주는 서버 — 는 이제 “털린 서버”의 동의어다. 1982년부터 지금까지 SMTP에 일어난 가장 중요한 사건은, “relay”라는 단어가 안에서부터 텅 비워졌다는 것이다. 그런데 단어 자체는 그대로라 거의 아무도 눈치채지 못했다.

2026년에 “relay”가 실제로 뭘 뜻하는지 풀어보자. 이 혼동이 사람들의 디버깅 시간을 진짜로 잡아먹으니까.

submission은 relay가 아니다

“메일이 안 나가요” 티켓의 절반을 해결해주는 구분이 이거다. submission과 relay는 우연히 같은 프로토콜을 쓸 뿐, 전혀 다른 두 동작이다.

submission은 당신의 클라이언트가 메시지를 당신의 서버에 건네는 것 — Thunderbird가 메일 제공사로, PHP 스크립트가 SendGrid로. 인증한다. 서버가 당신을 안다. 당신이 보낼 권한이 있음을 증명했으니 발신 메일을 받아준다.

relay는 한 서버가 조직 경계를 넘어 다른 서버에 메시지를 건네는 것 — 당신 제공사의 발신 MTA가 수신 도메인의 inbound MX로. 로그인은 없다. 수신 측이 받아주는 이유는 발신자가 인증해서가 아니라, 자기가 그 도메인의 최종 목적지이고 자기 앞으로 온 메일을 받을 의향이 있어서다.

SMTP의 첫 16년 동안 둘은 모두 port 25에서 돌았고 아무도 선을 긋지 않았다. 스팸이 그걸 재앙으로 만들기 전까지는 괜찮았다. 한 소켓이 인증된 submission 익명 relay를 동시에 받으면, 설정이 잘못된 서버 하나하나가 공짜 스팸 대포가 된다.

그래서 1998년 12월, Gellens와 Klensin이 RFC 2476을 내고 둘을 갈라놨다. submission은 port 587로 옮겼다. relay는 25에 남겼다. 그렇게 생겨나 지금도 유효한 규칙은 잔인할 만큼 단순하다. port 25는 서버끼리 얘기하는 곳, port 587(또는 465)은 사람·앱이 자기 서버와 얘기하는 곳. 앱에서 메일을 보내려고 설정하는데 port 25에 손이 간다면 거의 틀린 거다. ISP가 가정용 네트워크에서 발신 25를 막는 이유가 바로 이거다 — 거기서 시작되는 정상 트래픽이 더는 없으니까.

port 465엔 나름의 코미디가 있다. 90년대 말에 폐기됐다가 20년을 붕 떠 있었고, 2018년 RFC 8314가 implicit-TLS submission용으로 공식 부활시켰다. 465와 587은 같은 일을 한다 — 465는 STARTTLS로 대화 중간에 암호화로 올라타는 대신, 첫 바이트부터 암호화한다는 차이뿐이다.

보내기를 누르면 실제로 벌어지는 일

메시지 하나를 끝까지 따라가 보자.

  1. submission. 클라이언트가 제공사로 587을 열고, STARTTLS를 돌리고, 인증하고, 메시지를 보낸다. 이제 제공사 MTA가 그걸 소유한다.
  2. MX 조회. 그 MTA가 수신 도메인을 읽고, DNS에 MX 레코드를 물어, 우선순위가 가장 낮은(가장 선호되는) 걸 골라 IP로 푼다.
  3. relay. 당신 MTA가 수신 측 inbound MX로 port 25를 열고 배달한다. 이 여정에서 진짜 relay hop은 이거 하나뿐이다.
  4. 로컬 배달. 수신 MTA가 메시지를 메일박스에 떨군다. IMAP이나 POP이 나중에 읽는 사람에게 건넨다.

submission 하나, relay 하나, 배달 하나. 사람들이 머릿속에 그리는 그림 — 메일이 양동이 릴레이처럼 중간 relay 사슬을 통통 튀어 가는 모습 — 은 평범한 메일에선 사실상 더 이상 일어나지 않는다.

직접 증명할 수 있다. 아무 메일이나 열어 Received: 헤더를 아래에서 위로 읽어보라. 메시지를 거쳐 간 서버마다 하나씩 찍어둔다. 1995년이라면 그 스택이 세 조직에 걸쳐 다섯, 여섯 서버 깊이였을 수 있다. 지금은 보통 두세 줄이고, 그나마 대부분 같은 제공사 소속이다. 인터넷 메일 네트워크의 한가운데가 조용히 비워졌다.

relay는 어디로 갔나

사라졌다기보다 한곳으로 뭉쳤다. store-and-forward — 다음 hop이 죽어 있으면 서버가 메시지를 쥐고 있다가 나중에 재시도하는 것 — 는 여전히 SMTP의 핵심이고, 동기 프로토콜이라면 죽었을 장애를 메일이 버텨내는 이유다. 하지만 메시지가 거치는 독립적인 손의 수는 무너졌다.

두 힘이 그렇게 만들었다. 스팸이 열린 중간 서버를 죽였다 — 모르는 사람을 위해 relay하면 블록리스트에 오르게 되자, 모든 서버가 자기 인증 사용자나 자기 도메인을 위해서만 relay하도록 걸어 잠갔다. 그리고 집중화가 마무리를 지었다 — 세상 메일박스의 큰 몫이 소수 제공사 뒤에 모여 있으면, “조직 경계를 넘는 서버 대 서버”는 점점 거인 하나가 다른 거인에게 넘기는 일이 된다. 한 hop, 끝.

신뢰 모델이 뒤집혔다

여기가 챙겨둘 대목이다. SMTP는 relay-by-default로 시작했다. 모두를 믿고, 뭐든 넘긴다. 지금은 relay-by-exception이다. 아무도 믿지 말고, 자기가 의도된 목적지이거나 인증된 소유주일 때만 메시지를 받는다. 같은 동사, 정반대 자세.

그 이후 볼트로 박은 모든 것 — SPF, DKIM, DMARC, 그 인증 서커스 전부 — 은 원래 프로토콜이 한 번도 묻지 않았던 질문에 답하려고 존재한다. 1982년엔 물을 필요가 없었으니까. 애초에 내가 이 메시지를 날라야 하나? open relay는 답이 늘 예라고 가정했다. 30년의 악용이 가르쳐준 답은 거의 항상 아니오였고, 우리는 그 “아니오”를 DNS 레코드에 새겨 넣는 일을 그때부터 해오고 있다.

그러니 누가 “SMTP relay 좀 설정해줘”라고 하면, 멈춰서 어느 동작을 말하는지 물어라. 앱에서 메일을 보내려는 거면 그건 submission이다 — 인증하고, 587이나 465를 쓰고, 진짜 relay hop 하나는 제공사가 대신 밟게 둬라. 정말로 다른 서버를 위해 메일을 relay하는 박스를 원하는 거면, 누가 그걸 쓸 수 있는지 아주 신중하게 물어라. 인터넷은 그 답이 “모두”가 될 수 없게 만드는 데 25년을 썼다.

토론 참여

← 블로그로 돌아가기