문제

전달을 설정했습니다 — @yourdomain.com 별칭을 Gmail로 보내거나, 퇴사자 메일을 관리자에게 돌리거나, catch-all을 지원 함으로 몰아주는 식으로. 그리고 아무도 안 볼 동안만 정확히 잘 작동했습니다. 그러다 전달된 메일이 스팸함으로 가기 시작하거나 SPF·DMARC 얘기를 하며 반송되는데, 똑같은 메일을 직접 보내면 멀쩡히 도착합니다. 메일에서 바뀐 건 없습니다. 바뀐 건 전달이 조용히 깨뜨린 것 — 현대 메일이 돌아가는 유일한 기반, 인증입니다.

“그냥 전달하면 돼”라고 할 때 아무도 경고 안 하는 부분이 있습니다. 전달은 중립적인 통과가 아닙니다. 서버가 메시지를 다음으로 넘기는 순간, 다음 홉 입장에서는 당신 서버가 발신자가 됩니다 — 그리고 발신자야말로 SPF·DKIM·DMARC가 검증하려고 만든 대상입니다. 순진하게 한 전달은 셋 다 실패하고, 그것도 우연이 아니라 설계상 그렇게 됩니다.

전달이 메시지에 실제로 하는 일

왜 깨지는지 보려면, 똑같아 보이지만 다른 두 개의 “from”을 갈라야 합니다:

  • 봉투 발신자(MAIL FROM, return-path라고도 함) — SMTP 계층의 주소로 반송이 여기로 갑니다. SPF가 검사하는 게 이겁니다.
  • 헤더 From: — 수신자가 메일 앱에서 보는 주소. DMARC 정렬이 신경 쓰는 게 이겁니다.

전달하면 수신 서버는 접속 IP — 당신 포워더의 IP — 를 봉투 발신자의 도메인으로 SPF 대조합니다. 봉투 발신자가 여전히 원 도메인이면, 그 SPF 레코드는 당신 포워더를 들어본 적이 없으니 SPF가 fail을 냅니다. 문제 전체를 한 문장으로: SPF는 마지막 홉을 인증하는데, 전달은 원래 SPF 레코드가 모르는 홉을 하나 더한다.

깨지는 3가지, 순서대로

1. IP가 바뀌어 SPF가 실패한다. 이건 100% 벌어집니다. 해법은 Sender Rewriting Scheme(SRS)입니다. 포워더가 relay 전에 봉투 발신자를 자기 도메인으로 재작성하면, 다음 서버의 SPF 검사가 당신 포워더의 SPF 레코드 — 당신 IP가 들어 있는 — 에 대조돼 통과합니다. 성숙한 전달(메일박스 제공자, cPanel, 전문 전달 서비스)은 SRS를 자동 적용합니다. 손으로 만든 .forward·procmail·sieve 규칙은 대개 안 합니다. “그냥 전달 규칙 하나 넣었을 뿐”이 메일 반송을 시작하는 전형적 경로인 이유죠.

2. 포워더가 메시지를 편집하면 DKIM이 실패한다. DKIM은 전달 홉을 온전히 넘을 수 있는 유일한 인증법입니다. 연결이 아니라 메시지 내용에 서명하기 때문입니다. 깨끗한 relay는 서명을 유효하게 둡니다. 하지만 서명한 것을 바꾸는 순간 깨집니다 — [EXTERNAL] 제목 접두어, 본문에 붙는 푸터·면책 문구, 보안 게이트웨이의 링크 재작성, 문자셋 변환, 심지어 과한 줄바꿈 재정리까지. 이게 엄청나게 중요한 이유는, 살아남은 DKIM이야말로 SPF가 사라진 뒤에도 전달 메일의 DMARC를 통과시키는 것이기 때문입니다. DKIM까지 깨면 DMARC가 딛고 설 마지막 다리를 없앤 겁니다. 전달 전용 흐름에서는 제목 태깅과 첨부 푸터를 끄세요.

3. 루프와 반송 폭풍. 전달 사슬은 인증과 무관한 라우팅 실패를 부릅니다. A를 B로 전달하는데 B가 다시 A로 전달하면 루프가 생기고, 서버는 홉 수를 제한해 거부합니다(Exchange Online은 554 5.4.14 Hop count exceeded를 냅니다). 더 나쁜 건 catch-all 전달입니다. *@yourdomain.com을 함으로 몰면 존재하지 않는 주소로 오는 스팸까지 전부 전달하게 되고, 당신 IP에서 반송이 나가며 발송 평판을 태웁니다. catch-all이 아니라 특정 별칭만 전달하세요.

설정하고 확인하는 법

순서가 중요합니다 — 전달을 믿기 전에 인증부터 점검하세요:

  1. 포워더가 SRS를 하는지 확인. 전달 서버를 직접 관리한다면 SRS(“sender rewriting” / “envelope from rewriting”)가 켜졌는지 확인하세요. 제공자 전달을 쓴다면 거의 확실히 켜져 있습니다. 날 .forward·sieve redirect로 전달한다면 안 켜졌다고 가정하세요.
  2. DKIM이 살아남는지 확인. 전달을 거쳐 테스트 메일을 보내고, 도착한 사본의 Authentication-Results 헤더를 보세요. dkim=pass에 d= 도메인이 보이는 From: 도메인과 일치해야 합니다. DKIM이 fail이거나 없으면, 경로 어딘가가 메시지를 수정하고 있습니다.
  3. 메시지 재작성 범인 찾기. DKIM이 깨지면 원인을 추적하세요: 제목 태깅, 면책 문구, 링크 보호, 백신·보안 게이트웨이 재작성. 전달 흐름에서 이것들을 끄세요.
  4. ARC 확인. 신뢰받는 포워더가 ARC(Authenticated Received Chain) 헤더를 붙이면, ARC를 존중하는 수신자(Gmail이 존중합니다)는 SPF가 깨졌어도 원 인증 결과로 메일을 받아줄 수 있습니다. ARC는 완화책이지 보장이 아닙니다 — 모든 수신자가 존중하진 않습니다.
  5. 루프와 catch-all 제거. 전달 지도를 그려 서로를 가리키는 게 없는지 확인하세요. catch-all 전달은 명시적 별칭으로 바꾸세요.

DechoNet으로 확인하기

  • 이메일 / SPF·DMARC 진단은 도메인의 SPF·DKIM·DMARC 상태를 수신 서버가 보는 방식으로 읽습니다 — 그래서 전달에 기대기 전에, 도메인이 정렬된 DKIM 키와 DMARC 정책을 게시하고 있는지 확인할 수 있습니다. SPF가 사라진 뒤 전달 메일을 살아 있게 하는 게 바로 이것입니다.
  • DNS 조회는 날 TXT 레코드를 보여줘, DKIM 셀렉터와 DMARC 레코드가 실제로 존재하고 해석되는지를 짐작이 아니라 눈으로 확인하게 해줍니다.

해결 체크리스트

  • 전달 서버가 SRS(봉투 발신자 재작성)를 적용하는지 확인. 날 .forward·procmail·sieve 규칙은 대개 안 합니다.
  • 전달을 거쳐 테스트를 보내고 Authentication-Results를 확인 — From: 도메인에 정렬된 dkim=pass가 나와야 합니다.
  • 전달 전용 흐름에서 제목 태깅·푸터·면책 문구·링크 재작성을 꺼 DKIM이 살아남게 합니다.
  • catch-all 전달은 주소별 명시 별칭으로 교체합니다.
  • 홉 수 초과 거부를 부르는 루프(A→B→A)가 없는지 전달 지도를 추적합니다.

언제 확대할까

  • SRS를 켜고 DKIM이 살아남는데도 전달 메일이 DMARC를 계속 실패한다면, 문제는 정렬입니다. SRS는 포워더 도메인으로 SPF를 통과시키는데 그건 From: 도메인과 더는 일치하지 않으니, DMARC는 오직 DKIM으로만 통과할 수 있습니다. 원 발신자가 애초에 DKIM 서명을 하는지부터 확인하세요 — 안 하는 곳도 있습니다.
  • 포워더를 직접 운영하는데 하위 수신자가 relay 메일을 안 받아준다면, 그들이 ARC를 존중하는지, 당신 포워더가 ARC 체인을 내보내는지 보세요. 살아남은 DKIM도 존중되는 ARC도 없으면, 스푸핑 차단(p=reject) 도메인에서 온 전달 메일은 계속 실패합니다 — 그건 발송 도메인의 정책이 설계대로 작동하는 것이지, 전달 쪽에서 고칠 수 있는 게 아닙니다.

내 도메인에서 바로 확인

무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.