Email SPF (Sender Policy Framework)
Email에서 기본적으로 보안상 중요한 것은 송신자 인증 처리이다. 이메일의 송신자 인증처리 중 대표적인 것이 DKIM, DMARC, SPF 가 있는데 이 중에서 SPF에 대해서 기록한다.
SPF (Sender Policy Framework)
SPF는 일종의 메일 발송 서버 등록 제도로 해당 도메인을 통해서 이메일을 보낼 수 있도록 허용된 IP 주소를 지정할 수 있다. DNS 에 등록된 TXT 타입의 레코드를 통해서 도메인에 대한 허용된 메일 발송 IP를 정의할 수 있다.
SPF 운영
HELO, MAIL FROM identity (SPF 체크 대상 도메인)
- SMTP 프로토콜 상의 MAIL FROM 명령은 반송경로(reverse-path)를 표기하는데 사용됨.
- RFC 2811은 반송경로 표기를 의무화 하지 않으므로 MAIL FROM이 blank sender(<>)와 같은 표기를 허용함.
- 이 경우 MAIL FROM identity는 localpart로 'postmaster'와 HELO identity를 사용함.
- SPF 클라이언트는 MAIL FROM identity를 확인해야 함.
- MAIL FROM identity는 SPF 검사 수행 절차에 적용이 되어야 함.
발송 허용 아이피 레코드 출판 (Publishing Authorization)
- SPF를 사용할 도메인은 유효한 SPF 레코드를 출판해야 함.
- SPF 레코드는 HELO 혹은 MAIL FROM으로 식별된 도메인에 대한 발송 허용 IP를 확인하는 데 사용됨.
- SPF 사용중 메일 발송 환경에 변화가 생겨 이를 변경해야 할 경우 이 변화를 수용하기 위한 기간이 필요하며 이 기간 중 기존의 레코드와 새롭게 작성된 것 중 어느 것을 사용하는 메일도 수용할 수 있는 레코드를 출판해야 함.
메일 수신 서버의 SPF 레코드 확인
- 메일 수신 서버는 각 메일 메시지에 대해 일련의 SPF 검사를 수행할 수 있음.
- 적어도 MAIL FROM identity는 확인 되어야 하고 HELO identity도 사전에 확인하는 것을 권장함.
- SPF 검사를 수행시 올바르게 구현된 검사 수행 절차에 맞게 검사를 수행해야 함.
- 검사 수행 절차에 따라 평가 시에 검사 수행 절차에 전달되는 인수는 아래와 같음. (발신자 정보)
- <IP> : 메일 발송시 사용된 SMTP 발송 IP 주소
- <domain> : MAIL FROM 혹은 HELO에서 입력된 도메인 정보
- <sender> : MAIL FROM 혹은 HELO 입력 정보
SPF 검사 수행 결과
결과 | 설명 | 기본동작 |
None | 발신 도메인이 SPF 레코드를 등록하지 않았거나 제공된 발신자 정보에서 도메인 정보를 구할 수 없음. 적합한 발신지인지 여부를 판정할 수 없음. |
수신 |
Neutral | 발신 도메인에서 자신의 도메인에서 발송되었다고 하는 메일에 대하여 위조여부를 판단하기를 원하지 않음을 나타냄. Neutral로 판정된 메일의 처리는 None과 동일하게 취급되며 이 옵션은 SPF 시험운영등의 과정에서 사용됨. |
수신 |
Pass | 적합한 SPF 레코드를 찾았으며 레코드에서 발송 시스템의 domain 사용이 인증됨을 확인. | 수신 |
Fail | 적합한 SPF 레코드를 찾았지만 SMTP 클라이언트의 domain 사용 권한이 레코드에서 명시적으로 거부됨. | 거부 (5XX 응답) |
SoftFail | Fail과 Neutral의 중간 정도의 값을 나타냄. 발신 도메인이 메일 포워딩 등의 서비스를 통해 적법하게 위조될 수 있음을 나타냄. Fail 정책으로 변경하기 전의 과도기인 경우에도 사용. |
수신 (Received-SPF 헤더에 표시) |
TempError | 메일 수신 서버에서 SPF 결과 값 확인시 일시적인 장애가 발생하였음을 나타냄. | 거부 (4XX 응답) |
PermError | SPF 레코드 문법 오류 등의 경우 발생. | 거부 (5XX 응답) |
SPF 결과 값의 표기
수신 메일 헤더에 Received-SPF 키워드를 사용하여 Received 헤더 상단에 SPF 확인에 대한 판정 값을 기록한다.
ex) Bitbucket cloud로 부터 수신된 메일
Received-SPF: pass(localhost: SPF record at am.bitbucket.org designates XXX.XXX.XXX.XXX as permitted)
SPF 검사 수행 절차
- <domain>에 대한 적합성 여부 체크 - 오류가 있는 경우 Fail을 결과로 처리. <sender>가 존재하지 않는 경우 postmaster로 처리.
- <domain>에 대한 TXT 레코드 조회 - 해당 도메인이 존재하지 않을 경우 Fail로 결과로 처리. DNS 장애로 인해 오류가 발생한 경우 TempError를 결과로 처리.
- 2번에서 얻은 TXT 레코드 중에서 레코드 헤더가 "v=spf1"으로 시작하는 레코드를 선정. "v=spf1"으로 시작되는 레코드를 찾을 수 없는 경우 "None"을 결과로 처리.
- 3번에서 얻은 SPF 레코드 문법적 오류를 체크. 오류 확인시 PermError를 결과로 처리.
- 메일 발송 <IP>와 <domain>, <sender> 정보와 SPF 레코드 정보를 기반으로 SPF 검사 수행 결과를 판단.
SPF 레코드 정의
매커니즘 (mechanism)
- SPF 레코드에서 도메인은 매커니즘을 통해서 정의된다.
- 하나의 레코드에 매커니즘은 하나도 사용되지 않거나 여러 개의 매커니즘을 사용할 수 있다.
- 매커니즘은 적법한 메일 발송 호스트를 명시하거나 다른 메일 정책들을 명시하는 데 사용된다.
- prefixes
"+" | Pass |
"-" | Fail |
"~" | SoftFail |
"?" | Neutral |
- all
- all 매커니즘은 모든 경우에 해당되며 항상 모든 레코드의 마지막에 위치한다.
v=spf1 -all
해당 도메인은 메일을 발송하지 않음을 명시함
- a (a, a:domain, a:domain/cidr-length, a/cidr-length)
- 해당 도메인의 모든 A 레코드 중 하나가 발송 호스트의 IP와 일치하도록 할 때 적용한다.
- 도메인명이 명시되지 않은 경우 현재의 도메인이 사용된다.
v=spf1 a:example.com -all
example.com 도메인의 A 레코드와 동일한 서버에서만 메일 발송을 허가하며
그 이외의 호스트에서는 메일을 발송하지 않는다.
v=spf1 a:mailer.example.com -all
mailer.example.com 도메인의 A 레코드와 동일한 서버에서만 메일 발송을 하가하며
그 이외의 호스트에서는 메일을 발송하지 않는다.
- mx (mx, mx:domain, mx:domain/cidr-length, mx:cidr-length)
- 해당 도메인의 모든 MX 레코드의 A 레코드 중 하나가 발송 호스트의 IP와 일치 하도록 할 때 적용한다.
- 도메인이 명시되지 않은 경우 현재 도메인이 사용된다.
v=spf1 mx:example.com -all
example.com 도메인의 MX 레코드로 지정된 서버에서만 메일을 발송할 수 있다.
v=spf1 mx:example.com/24 -all
example.com 도메인의 MX 레코드로 지정된 서버의 C 클래스 네트워크의 주소에서 메일을 발송할 수 있다.
- ptr (ptr, ptr:domain)
- 발송 호스트의 IP의 PTR 쿼리를 통해 얻어진 도메인과 일치하도록 할 때 적용된다.
v=spf1 ptr:example.com -all
메일 발송 아이피의 PTR 쿼리를 한 결과가 example.com인 경우에만 메일 발송을 허용한다.
- ip4
- 발송 호스트의 IP를 CIDR로 정의된 네트워크 IP 범위 내에 위치시킬 때 적용된다.
- CIDR 범위를 한정하는 /XX 가 명시되지 않은 경우 /32가 생략된 것이다.
v=spf1 ip4:192.168.0.1/24 -all
192.168.0.1 ~ 192.168.0.255 IP 대역에서만 메일 발송을 허용한다.
- ip6
- IPv6의 발송 대역을 정의한다.
- exists
- exists로 정의된 도메인에 대해 쿼리를 수행하여 A 레코드가 존재하는 경우 메일 발송을 허용한다.
- 아래는 am.bitbucket.org 발송 도메인에 대한 SPF 레코드 확인이다.
exists:%{i}._spf.sparkpostmail.com에서 %{i}는 ip address를 의미하는데 메일 수신 서버 입장에서 연결된 발송 IP를 대입한다.
예를 들어 접속 아이피가 192.168.0.123 이라고 한다면 192.168.0.123._spf.sparkpostmail.com의 A 레코드가 존재하는지 여부를 체크한다.
- include
- 발송 호스트의 IP가 해당 도메인의 외부에 위치할 때 include를 사용하여 외부 발송 도메인을 정의한다.
- 정의된 도메인이 적법한 레코드를 사용하고 있지 않은 경우 PermError를 리턴한다.
- 아래는 kakao.com 도메인에 대한 SPF 레코드 확인이다.
변형자 (modifier)
변형자는 옵션으로 사용되며 하나의 SPF 레코드에 한번만 사용된다.
정의되지 않은 변형자는 처리되지 않고 생략된다.
- redirect
- redirect는 SPF 레코드를 명시된 값으로 대치한다.
- redirect는 SPF 정책을 호스팅하는 다른 도메인 이름에 대한 포인터이며 여러 도메인이 동일한 SPF 정책을 공유할 수 있다.
- 동일한 이메일 인프라를 공유하는 많은 양의 도메인으로 작업할 때 유용하다.
v=spf1 redirect=example.com
example.com 의 SPF 레코드를 사용하여 결과 값을 판정하고
example.com에 SPF 레코드가 정의되어 있지 않을시 unknown을 리턴한다.
- exp
- SMTP 수신자가 SPF 판정 값에 따라 메시지를 거부할 경우 메시지 거부 이유를 명시하는 데 사용된다.
v=spf1 mx -all exp=explain._spf.%{d}
발송 도메인의 MX 레코드에서 발송한 메일이 아닌 경우 메일 수신을 거부하며
explain._spf.<domainname> 에 명시된 안내문을 리턴한다.
SPF 레코드 매크로 정의
많은 메커니즘과 변형자는 마크로 확장을 사용하여 간결하게 표현할 수 있다.
마크 | 설명 |
%{s} | <sender> |
%{l} | local-part of <sender> |
%{o} | Domain of <sender> |
%{d} | <domain> |
%{i} | <ip> |
%{t} | Current time stamp |
%{p} | The validated domain name of <ip> |
%{v} | The string "in-addr" |
%{h} | HELO/EHLO domain |
%{c} | SMTP client IP |
%{r} | Domain name of host performing the check |
SPF 관련 보안사항
다른 인터넷 프로토콜과 같이 SPF 역시 다음과 같은 공격의 대상이 될 수 있다.
- 공격 대상 도메인에 대하여 다량의 DNS 참조를 시행하는 악성 SPF 레코드를 출판하여 공격대상 도메인의 CPU, 메모리 사용량을 증가시키는 DoS 공격
- 공격 대상 도메인에 대하여 출발지를 달리하는 다량의 메일을 발송하여 해당 도메인의 DNS 서버의 무력화를 시도하는 공격
SPF의 매커니즘에서 "all", "ip4", "ip6"는 DNS lookup을 필요로 하지 않는다.
메일 발송서버의 IP 변동이 많은 경우 효율적인 관리를 위해서 불가피하게 "a:" 혹은 "mx:" 레코드가 사용되어야 하는 경우를 제외하고는 질의수가 최소화된 SPF 레코드를 출판하는 것이 좋다. (ip4:xxx.xxx.xxx.xxx/cidr...)
참고링크
https://www.ietf.org/rfc/rfc4408.txt
https://www.mailhardener.com/blog/spf-redirect-explained