메인 콘텐츠로 이동하기
  1. 서버구축기/

메일서버 수신 인증 점검하기 (SPF / DKIM / DMARC 검증편)

·6 분

이 글이 왜 필요한가 (송신 검증 vs 수신 검증) #

메일 서버를 처음 구축하면 보통 “내가 보낸 메일이 스팸함에 안 가게” 하는 데 집중합니다. 그래서 mail-tester.com 같은 곳에서 DKIM 10/10 받으면 “다 끝났다"고 생각하기 쉬운데, 사실 그건 내가 보내는(송신) 메일에 서명을 잘 달고 있는지만 확인한 겁니다.

이 글에서 다루는 건 반대 방향, 즉 다른 사람이 내 서버로 보낸 메일을 받을 때, 그 메일이 진짜인지(SPF/DKIM/DMARC 통과하는지) 내 서버가 검사하고 있는가입니다. 이 검증이 빠져 있으면, 발신자를 위조한 스팸/피싱 메일이 그대로 내 받은편지함에 들어올 수 있습니다.

용어부터 짧게 정리하면:

  • SPF (Sender Policy Framework): “이 도메인 메일은 이 IP에서만 보내야 정상"이라고 DNS에 미리 선언해두고, 받는 쪽이 실제 발신 IP와 대조하는 방식입니다.
  • DKIM (DomainKeys Identified Mail): 메일 본문/헤더에 암호 서명을 붙여서, 중간에 내용이 바뀌지 않았고 진짜 그 도메인에서 보냈다는 걸 증명하는 방식입니다.
  • DMARC (Domain-based Message Authentication): SPF/DKIM 검사 결과를 종합해서 “둘 다 실패하면 어떻게 처리할지(거부/격리/통과)“를 DNS에 선언해두는 정책입니다.

셋 다 “송신"과 “수신” 양쪽에 각각 관련 기능이 있는데, 이 글은 수신 검증에 집중합니다.


1단계: 지금 뭐가 켜져 있고 뭐가 빠져 있는지 확인하기 #

1-1. DKIM이 “검증 모드"로 동작하는가 #

sudo opendkim-testkey -d snsoz.com -s mail -vvv

이 명령은 송신용 확인입니다. 내 DKIM 개인키/공개키(DNS TXT 레코드)가 서로 짝이 맞는지 확인하는 것이지, 수신 메일을 검증하고 있는지는 알려주지 않습니다.

수신 검증 여부는 아래로 확인합니다.

grep -E "Mode|Socket" /etc/opendkim.conf

결과 예시와 의미:

결과 의미
Mode s 서명(송신)만 함. 수신 검증 안 함.
Mode v 검증(수신)만 함. 서명 안 함.
Mode sv 서명 + 검증 둘 다 함. (원하는 상태)

s만 있고 v가 없다면 아래처럼 고쳐줍니다.

sudo nano /etc/opendkim.conf

Mode 줄을 찾아서:

Mode    sv

로 바꾸고 저장한 뒤 재시작합니다.

sudo systemctl restart opendkim

참고: smtpd_milters에 이미 opendkim 소켓이 등록돼 있다면(대부분 처음 DKIM 서명 설정할 때 등록해뒀을 것입니다), Postfix 쪽은 따로 손댈 게 없습니다. Modev만 추가하면 같은 milter가 수신 메일도 검증하기 시작합니다.

1-2. SPF 검증기가 설치돼 있는가 #

dpkg -l | grep spf

또는

postconf -n | grep policy

postfix-policyd-spf-python 또는 postfix-policyd-spf-perl 같은 패키지가 안 보이고, postconf -n 결과에도 check_policy_service 관련 줄이 없다면 SPF 검증을 전혀 안 하고 있는 상태입니다. (2단계에서 설치)

1-3. DMARC 검증기가 설치돼 있는가 #

systemctl status opendmarc

또는

dpkg -l | grep dmarc

Unit opendmarc.service could not be found 같은 메시지가 뜨거나 dpkg 목록에 아무것도 안 잡히면 DMARC 검증도 안 하고 있는 상태입니다. (3단계에서 설치)

한 번에 세 가지 다 확인하고 싶으면:

grep Mode /etc/opendkim.conf
dpkg -l | egrep "spf|dmarc"
postconf -n | grep policy

2단계: SPF 검증 추가하기 #

설치 #

sudo apt update
sudo apt install postfix-policyd-spf-python

설치 확인:

dpkg -l | grep spf

master.cf에 SPF 검사 프로세스 등록 #

sudo nano /etc/postfix/master.cf

맨 아래에 추가:

policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

두 번째 줄은 반드시 탭(Tab)이나 스페이스로 들여쓰기가 돼 있어야 첫 줄과 이어지는 설정으로 인식됩니다. 그냥 줄바꿈만 하면 별개 서비스로 잘못 인식되니 주의하세요.

main.cf에서 실제로 검사하도록 연결 #

sudo nano /etc/postfix/main.cf

smtpd_recipient_restrictionscheck_policy_service 줄을 추가합니다. 기존에 이미 설정이 있다면 통째로 바꾸지 말고, 그 안에 한 줄만 끼워 넣으세요. 없다면 아래처럼 통째로 넣어도 됩니다:

smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_pipelining,
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    check_policy_service unix:private/policyd-spf,
    reject_unknown_client_hostname,
    reject_unauth_destination

check_policy_service가급적 뒤쪽(내 서버로 보내도 되는 사람인지 1차 필터링이 끝난 뒤)에 두는 게 일반적입니다. 너무 앞에 두면 SPF 조회 때문에 정상 발송자도 지연될 수 있습니다.

(빠졌던 부분) policyd-spf 자체 설정 파일 확인 #

기본 설정 파일은 보통 /etc/postfix-policyd-spf-python/policyd-spf.conf에 있습니다. 대부분 기본값으로 충분하지만, 문제가 생겼을 때 로그를 자세히 보고 싶으면 이 파일에서 debugLevel을 올려볼 수 있습니다 (0~4, 기본은 1).

sudo nano /etc/postfix-policyd-spf-python/policyd-spf.conf
debugLevel = 2

재시작 #

sudo systemctl restart postfix

확인 방법 #

외부에서 메일을 하나 보내달라고 한 뒤, 헤더를 열어보면 Received-SPF: Pass (...) 같은 줄이 붙어있어야 정상 동작하는 것입니다. 또는 실시간으로 로그를 보면서 확인할 수 있습니다:

sudo tail -f /var/log/mail.log | grep -i spf

3단계: DMARC 검증 추가하기 #

설치 #

sudo apt install opendmarc

opendmarc.conf 설정 #

sudo nano /etc/opendmarc.conf

원본 질문에는 소켓 줄만 있었는데, 실제로 동작하려면 최소한 아래 항목들이 채워져 있어야 합니다 (빠져 있으면 추가하세요):

AuthservID              mail.snsoz.com
TrustedAuthservIDs      mail.snsoz.com
Socket                  local:/run/opendmarc/opendmarc.sock
RejectFailures          false
Syslog                  true
SyslogFacility          mail
UMask                   0002

각 항목이 뭘 하는지:

  • AuthservID: 결과를 표시할 때 어떤 이름으로 표시할지(보통 자기 메일서버 도메인).
  • TrustedAuthservIDs: 위 값과 보통 동일하게 맞춥니다.
  • Socket: opendkim처럼 Postfix와 통신할 통로(유닉스 소켓) 경로.
  • RejectFailures: true로 하면 DMARC 검증에 실패한 메일을 바로 거부합니다. 처음 켤 때는 오탐(정상 메일이 걸리는 것)이 있을 수 있으니 false로 시작해서 로그만 쌓다가, 며칠 지켜보고 문제없으면 true로 바꾸는 걸 권장합니다.
  • Syslog / SyslogFacility: 검증 결과를 /var/log/mail.log에 남길지 여부.

(빠졌던 부분) 소켓 권한 문제 미리 막기 #

opendmarc는 opendmarc라는 전용 계정으로 실행되는데, Postfix는 postfix 계정으로 실행됩니다. 이 둘이 같은 소켓 파일을 주고받으려면 권한을 맞춰줘야 합니다. 이 단계를 빼먹으면 “Milter가 응답하지 않는다"거나 메일이 아예 지연/거부되는 문제가 흔히 발생합니다.

sudo gpasswd -a postfix opendmarc

opendkim을 처음 설정할 때도 같은 이유로 sudo gpasswd -a postfix opendkim을 했었다면, 이미 익숙한 절차일 겁니다.

서비스 활성화 #

sudo systemctl enable --now opendmarc
sudo systemctl status opendmarc

active (running)으로 뜨는지 확인하세요.

Postfix에 연결하기 #

sudo nano /etc/postfix/main.cf

기존:

smtpd_milters = unix:opendkim/opendkim.sock

수정 (opendmarc 추가):

smtpd_milters =
    unix:opendkim/opendkim.sock,
    unix:/run/opendmarc/opendmarc.sock

non_smtpd_milters =
    unix:opendkim/opendkim.sock,
    unix:/run/opendmarc/opendmarc.sock

한 줄로 써도 됩니다:

smtpd_milters = unix:opendkim/opendkim.sock,unix:/run/opendmarc/opendmarc.sock
non_smtpd_milters = unix:opendkim/opendkim.sock,unix:/run/opendmarc/opendmarc.sock

주의(빠졌던 부분): 경로 표기가 서로 다릅니다. opendkim 소켓은 unix:opendkim/opendkim.sock처럼 앞에 /가 없는 상대경로이고, opendmarc는 unix:/run/opendmarc/opendmarc.sock처럼 /로 시작하는 절대경로입니다. 우분투 기본 Postfix 패키지는 chroot가 꺼져 있어서(둘 다) 대부분 문제없이 동작하지만, 만약 milter 연결이 안 되는 문제가 생기면 아래 명령으로 chroot 설정부터 확인해보세요.

postconf -Mf | grep smtp

smtp inet n - n - - smtpd처럼 다섯 번째 칸이 n이면 chroot가 꺼진 정상 상태입니다. 혹시 y로 돼 있다면 opendkim처럼 상대경로로 통일하거나, /etc/postfix/master.cf에서 chroot 칸을 n으로 바꿔주세요.

또한, milter 서비스가 죽었을 때 메일이 전부 막히는 걸 원치 않는다면 아래 옵션도 함께 확인해두면 안전합니다 (기본값이 tempfail이라 milter가 안 살아있으면 메일이 전부 지연됩니다):

milter_default_action = accept

단, accept로 하면 milter가 죽었을 때 검증 없이 그냥 통과시킨다는 뜻이니, “검증이 원래 목적"이라면 오히려 tempfail(기본값) 그대로 두고 opendkim/opendmarc 서비스 자체가 죽지 않게 모니터링하는 쪽을 권장합니다.

재시작 #

sudo systemctl restart postfix

4단계: 실제로 잘 되는지 확인하기 #

설정만 하고 끝내지 말고, 꼭 실제 메일로 확인하세요.

방법 1: 받은 메일 헤더 직접 보기 #

Gmail 기준: 메일 열기 → 우측 상단 점 3개 → “원본 보기”. 헤더에서 Authentication-Results: 줄을 찾으면 아래처럼 보입니다.

Authentication-Results: mail.snsoz.com;
    dkim=pass header.d=example.com;
    spf=pass smtp.mailfrom=example.com;
    dmarc=pass header.from=example.com

셋 다 pass면 정상 동작하는 것입니다.

방법 2: 로그로 실시간 확인 #

sudo tail -f /var/log/mail.log | egrep -i "dkim|spf|dmarc"

이 상태로 외부 메일 계정에서 테스트 메일을 하나 보내면서 로그가 어떻게 찍히는지 보면 어디서 걸리는지 바로 알 수 있습니다.

방법 3: mail-tester.com #

이건 원래 송신 품질을 보는 도구라 수신 검증 자체를 알려주진 않지만, DNS의 SPF/DMARC 레코드 문법이 맞는지 교차 확인하는 용도로는 여전히 유용합니다.


자주 걸리는 문제 정리 #

증상 원인/확인
DKIM Modesv로 바꿨는데도 검증 결과가 헤더에 안 보임 smtpd_milters에 opendkim 소켓이 실제로 등록돼 있는지 postconf -n | grep milter로 확인
SPF policyd 설치했는데 헤더에 Received-SPF가 안 붙음 master.cf의 policyd-spf 항목 들여쓰기 확인, check_policy_service 줄이 smtpd_recipient_restrictions에 실제로 들어갔는지 재확인
opendmarc 재시작 후 메일이 전부 지연/거부됨 소켓 권한 문제일 가능성 높음 → sudo gpasswd -a postfix opendmarcpostfix, opendmarc 둘 다 재시작
systemctl status opendmarc가 바로 죽음(failed) /etc/opendmarc.conf 문법 오류 가능성 → journalctl -u opendmarc -n 50으로 에러 메시지 확인
DMARC는 pass인데 실제 스팸이 계속 들어옴 DMARC는 “From 헤더 도메인"만 검증합니다. 발신자가 아예 다른 도메인을 쓰는 일반 스팸은 DMARC로 못 거른다는 점을 기억하세요(SPF/DKIM/DMARC는 ‘도메인 위조’를 막는 것이지 스팸 전체를 막는 필터가 아닙니다)

요약 #

  1. grep Mode /etc/opendkim.confsv가 아니면 고치고 opendkim 재시작
  2. postfix-policyd-spf-python 설치 + master.cf/main.cf 연결 + postfix 재시작
  3. opendmarc 설치 + 소켓 권한(gpasswd) + main.cf milters 연결 + postfix 재시작
  4. 실제 메일 헤더의 Authentication-Results에서 세 개 다 pass 뜨는지 확인

이 네 단계만 순서대로 밟으면 “내가 보낸 메일 검사"뿐 아니라 “내가 받는 메일 검사"까지 갖춘 완전한 메일서버가 됩니다.