이메일에 관해, 당신이 지금 느끼는 것보다 훨씬 더 불편해야 할 사실이 하나 있다: 메일 서버 하나가 다른 서버에 메시지를 넘길 때 암호화는 선택이고, 그 암호화를 건너뛸지 말지를 두 서버 중 누구도 아닌 공격자가 결정할 수 있다.
그 메커니즘이 STARTTLS다. 보내는 서버가 포트 25로 받는 서버에 접속해 EHLO라고 말하면, 받는 서버가 자기가 지원하는 목록을 답으로 준다. 그 목록에 250 STARTTLS가 있으면 보내는 쪽이 평문 연결을 TLS로 업그레이드하고 메시지는 암호화돼 나간다. 없으면 보내는 쪽은 어깨를 으쓱하고 평문으로 보낸다. 20년 동안 “제공되면 암호화”의 대안은 “메일을 안 보냄”이었고, 메일을 안 보내는 건 암호화 없이 보내는 것보다 나쁜 결과였기 때문이다. 그래서 SMTP 암호화는 *기회주의적(opportunistic)*이 됐다: 되면 좋고, 절대 필수는 아니고.
구멍이 벌써 보일 것이다. 능력 목록은 TLS 핸드셰이크 전에 도착한다 — 그래야만 한다, 그게 업그레이드를 협상하는 방식이니까 — 즉 암호화되지 않은 채로 도착한다. 네트워크 경로에 앉은 공격자는 암호를 깰 필요가 없다. 그냥 받는 서버 응답에서 250 STARTTLS 줄을 지우면 된다. 보내는 서버는 암호화 제안이 없다고 보고 설계된 그대로 평문으로 내려가고, 공격자는 메시지 전체를 읽는다. 이게 STARTTLS 스트리핑 공격이다. 기회주의적 TLS에는 기억도 기대도 없어서 통한다. 모든 연결이 “어쩌면 암호화하겠지”에서 시작하고, “어쩌면”은 “안 함”으로 너무 쉽게 내려간다.
세션 안에서는 못 고친다
이 버그가 그렇게 오래 살아남은 이유는, 연결 밖의 정보 없이는 못 막기 때문이다. SMTP 세션 안에서 보내는 서버는 TLS를 지원하지 않는 받는 서버와, TLS 제안이 벗겨진 받는 서버를 진짜로 구별하지 못한다. 둘은 똑같아 보인다: EHLO 응답에 STARTTLS가 없음. 그 없음이 수상하다는 걸 알려면 보내는 서버가 미리, 공격자가 통제하지 못하는 채널을 통해 들어야 한다 — “이 도메인은 항상 TLS를 지원한다. 제안이 안 보이면 뭔가 잘못된 거다, 보내지 마라.”
그게 MTA-STS의 핵심 아이디어 전부다. 2018년 9월 RFC 8461로 표준화됐다. 도메인이 지속되는 약속을 발행하는 방법이다: 내 메일 서버는 유효한 인증서로 TLS를 지원하니, 강제하라. 보내는 서버가 그 정책을 한 번 받으면 STARTTLS 스트리핑은 더 안 통한다 — 암호화가 협상 테이블에 올라왔어야 함을 알기에, 안 올라오면 평문으로 내려가는 대신 전송을 거부한다. 다운그레이드 공격이 조용한 가로채기 대신, 시끄럽고 고칠 수 있는 전송 실패로 바뀐다.
“연결을 업그레이드하고 스트리핑에 저항하는, 지속되는 보안 정책을 발행한다”가 익숙하게 들린다면 맞다. HSTS다. 브라우저에게 “나랑은 무조건 HTTPS로만 말해”라고 하는 그 헤더. MTA-STS는 이메일용 HSTS다 — 같은 아이디어를 웹 대신 SMTP에 겨눈 것. 그래서 다들 어리둥절해하는 그 부분이 더 의미심장하다.
다들 어리둥절해하는 부분
그 정책을 발행하려면, 웹 서버를 돌려야 한다.
도메인은 MTA-STS를 두 조각으로 광고한다. 첫째는 _mta-sts.example.com의 DNS TXT 레코드로, 본질적으로 “나 정책 있어, 버전 ID는 이거”라고 말한다 — v=STSv1; id=20260624T000000. 이 레코드는 작고, 혼자서는 보내는 서버더러 진짜를 가지러 가라고 알리는 것 말곤 아무것도 안 한다. 진짜 — 둘째 조각 — 는 고정된 HTTPS URL에 있다: https://mta-sts.example.com/.well-known/mta-sts.txt. 보내는 서버가 그 서브도메인에 HTTPS 요청을 하면 실제 정책이 돌아온다:
version: STSv1
mode: enforce
mx: mail.example.com
mx: *.example.com
max_age: 604800
mode가 레버다. enforce는 목록에 있는 MX에 유효한 인증서로 TLS를 협상하지 못하면 전송을 거부한다는 뜻이다. testing은 시도하되 어쨌든 보내고 실패를 보고한다 — 진입로다. 실제 메일이 반송되기 전에 깨진 설정을 찾을 수 있다. none은 정책을 거둬들이는 중이라는 뜻. mx는 어떤 메일 서버가 정당한지 나열하고(와일드카드 허용), 공격자가 당신을 자기 서버로 돌려보내지 못하게 한다. max_age는 정책을 몇 초간 캐시할지로, 최대 1년이다.
정책을 DNS가 아니라 HTTPS로 제공하기로 한 선택이 이 설계 전체의 영리하고 논쟁적인 핵심이다. HTTPS는 인증을 공짜로 준다 — 정책이 Web PKI에 대해 검증된 연결로, 즉 당신 브라우저가 이미 신뢰하는 바로 그 인증 기관들로 전달되므로, 네트워크 공격자가 위조하거나 변조하지 못한다. 새 신뢰 인프라가 필요 없다. 그게 실용적 승리이고, 기술적으로 더 깔끔한 대안 대신 MTA-STS가 존재하는 이유다.
아무도 배포 못 한 더 깔끔한 대안
기술적으로 더 깔끔한 대안은 DANE다. DANE(SMTP의 경우 RFC 7672)은 메일 서버의 인증서 지문을 DNS의 TLSA 레코드에 직접 발행하고, 보내는 서버가 모든 연결에서 인증서를 그것과 대조한다. 웹 서버도, trust-on-first-use 틈도, 상업용 인증 기관 의존도 없다. 종이 위에선 MTA-STS보다 무조건 낫다.
요구 사항이 딱 하나 있다: DNSSEC. TLSA 레코드는 그걸 실은 DNS 응답이 암호학적으로 서명돼 있어야만 믿을 수 있다. 안 그러면 STARTTLS를 벗기는 그 공격자가 TLSA 레코드도 그냥 위조하면 되니까. 그래서 DANE는 DNSSEC의 모든 채택 문제를 물려받는다 — 그리고 DNSSEC는 20여 년이 지나도록 여전히 대다수 도메인에 배포돼 있지 않다. 존에 서명하고 키 롤오버를 관리하는 게 진짜로 어렵고, 체인이 깨지면 도메인이 통째로 죽기 때문이다. DANE는 인터넷 대부분이 끝내 채택하지 않은 의존성 뒤에 갇혀 있다.
이 갈림길이 MTA-STS의 모든 걸 설명한다. 저자들은 DANE를 보고, DNSSEC 뒤에 발이 묶인 아름다운 프로토콜을 보고, 의도적인 거래를 했다: 암호학적 순수성을 포기하고, 모두가 이미 가진 Web PKI에 기대서, 도메인더러 먼저 DNSSEC부터 풀라고 요구하지 않고 오늘 배포 가능한 무언가를 얻자. 구글도 규모에서 같은 베팅을 했다 — 2019년 Gmail의 MTA-STS 지원을 발표하며 주요 제공자 중 처음으로 그렇게 했고, 오늘까지도 MTA-STS는 지원하되 DANE는 지원하지 않는다. HTTPS에 거는 쪽이 DNSSEC에 거는 쪽보다 훨씬 더 많은 인터넷에 닿기 때문이 거의 확실하다.
설계의 이음매
이 거래가 공짜는 아니고, 이음매가 어디 있는지는 솔직할 가치가 있다. MTA-STS는 trust-on-first-use다. 보내는 서버가 당신 도메인에 처음 접속하는 바로 그 순간엔 캐시된 정책이 없으니 하나 가져와야 하고 — 공격자가 그 첫 HTTPS 요청을 막을 수 있으면, 보내는 서버는 정책이 있다는 걸 영영 모르고 보호는 조용히 적용되지 않는다. 캐시된 정책이 만료돼 갱신해야 할 때마다 그 창이 좁게 다시 열린다. DANE에는 이 틈이 없다. 검사가 모든 연결마다 DNS에서 일어나니까.
RFC는 이걸 솔직히 인정하고 옳은 완화책을 준다: 공격적으로 갱신하라. 캐시된 정책이 만료되길 기다리지 말고 — 일정에 따라 매일이나 매주, 백그라운드로 다시 가져와라. 그러면 공격자는 한 순간의 경합을 한 번 이기는 대신, 캐시 수명 내내 정책 발견을 지속적으로 막아야 보내는 서버를 어둠에 둘 수 있다. 이음매를 거의 0에 가깝게 좁힌다. 완전히 용접해 막진 못한다. 그게 DNSSEC 대신 배포 가능성을 택한 정직한 비용이고, 대부분의 도메인에겐 명백히 치를 만한 비용이다. 실제로 켜는 프로토콜이, 끝내 배포 안 하는 더 강한 프로토콜을 이기니까.
testing으로 켜고 리포트를 읽어라
같이 켜야 할 동반 프로토콜이 있다: TLS-RPT(RFC 8460). 보내는 서버에게 TLS 협상이 어땠는지 — 성공, 실패, 그리고 결정적으로 정책 적용 실패 — 매일 요약을 메일로 보내달라고 요청하는 두 번째 TXT 레코드다. 이게 없으면 보안 통제를 눈 감고 배포하는 셈이고, MX 호스트 하나의 인증서 문제 때문에 enforce 모드가 정당한 메일을 조용히 반송하고 있어도 알 길이 없다. 이게 있으면 testing 모드로 시작해, 몇 주간 리포트를 지켜보고, 거기 드러나는 걸 고친 다음에야 enforce로 넘긴다. 리포트가 배포와 추측의 차이다.
정리하면: MTA-STS는 이메일 암호화의 수십 년 된 진짜 구멍에 대한 진짜 해법이고, DNSSEC 없이 배포 가능하도록 일부러 설계됐고, 지구상 가장 큰 메일박스 제공자의 축복을 받았다 — 그런데도 여전히 소수의 도메인에만 있다. 논쟁적이라서가 아니다. 구멍을 막는다는 게, 정적 텍스트 파일 하나를 제공하려고 자체 인증서를 가진 전용 mta-sts. 서브도메인을 세우고, 이미 SPF와 DKIM과 DMARC로 붐비는 DNS 존에 TXT 레코드를 두 개 더 얹는 일이기 때문이다. 그것도, 그날이 오기 전까진 추상적으로 느껴지는 위협 — 네트워크 경로에서 STARTTLS를 벗기는 능동적 공격자 — 을 위해서. 아무도 모르는 그 프로토콜이 무명인 건 나빠서가 아니다. 일은 지루하고 위험은 조용해서다. 그리고 그 조합이야말로 좋은 보안이 대개 죽는 방식이다.