0.要約
SPFは以下3つの登場人物の組み合わせによるもの。
- メールの送信者(正規の送信者、Amazon SESなど代理の送信者、スパムメール業者など)
- ドメインの持ち主(メール送信元とされる)
- メールの受信者
それぞれが実際にやること。
- 送信元を主張してメールを送る → HELO, MAIL FROM(Return-Path/エンペローブID)に含まれるドメイン
- 送信元と騙られないようにSPFレコード(送信元として承認しているホスト)を設定する
- 受信者(MTA)が1.と2.の情報を組み合わせてSPFを確認する
メールヘッダは情報が多く、そこからSPFの仕組みを理解するのは難しいので、
SMTPコマンドでメールを送る際に利用される情報を整理してから、
メールヘッダを読み解いてSPFを理解していきます。
参考資料
telnetでメール送信(ash.jp)
1.SMTPコマンドでメールを送る
SMTPコマンドのおさらい
SMTPコマンドでは、以下の順にデータを入力してメールを送信します。
SMTPコマンド | メールヘッダに書かれる情報 | 内容 | 詐称 |
---|---|---|---|
HELO | Received | 送信者が送り元のドメインを知らせる | できる |
Mail From: *1 | Return-Path | 送信者が送り元のメールアドレスを知らせる | できる |
RCPT TO: | Delivered-To | 送信先のアドレス | ? |
DATA | (本文として記載) | From, Subjectなどを含めた本文全体 | - |
*1 Return-Path, エンベロープFromなどの呼び方があります。
virtualboxなどの仮想マシンのMTAに対しローカルからSMTPコマンドを試してみます。(CentOS8 stream)
下準備
CentOS8StreamをベースにMTAを準備します。
(VirtualBoxの場合、Adapter1をNAT、Adapter2をHost-only AdapterにしてAdapter2からSSHでつなぎます)
ここでは仮想マシンのIPを192.168.56.101
とします。
% ssh root@192.168.56.101
Postfixを入れます
# dnf install -y postfix telnet
Postfixが受け付けるインターフェース、mydomain、mydestinationを修正します。
# cp -vp /etc/postfix/main.cf /etc/postfix/main.cf.orig
# sed -i s/^#inet_interfaces\ =\ all/inet_interfaces\ =\ all/g /etc/postfix/main.cf
# sed -i s/^inet_interfaces\ =\ localhost/#inet_interfaces\ =\ localhost/g /etc/postfix/main.cf
# sed -i s/^#mydomain\ =\ domain.tld/mydomain\ =\ smtp-test.local/g /etc/postfix/main.cf
# sed -i s/^mydestination\ =\ \$myhostname,\ localhost.\$mydomain,\ localhost/#mydestination\ =\ \$myhostname,\ localhost.\$mydomain,\ localhost/g /etc/postfix/main.cf
# sed -i s/^#mydestination\ =\ \$myhostname,\ localhost.\$mydomain,\ localhost,\ \$mydomain$/mydestination\ =\ \$myhostname,\ localhost.\$mydomain,\ localhost,\ \$mydomain/g /etc/postfix/main.cf
Firewallに穴を開けます。
# firewall-cmd --add-port=25/tcp --permanent
# firewall-cmd --reload
# systemctl start postfix
Virtualbox内のSMTPに接続して接続先サーバーのユーザーに送信
ローカルから接続してみます。
以下3つのデータでセットします。
HELO: example.com
MAIL FROM: user@example.com
RCPT TO: root@smtp-test.local
% telnet 192.168.56.101 25
Trying 192.168.56.101...
Connected to 192.168.56.101.
Escape character is '^]'.
220 localhost.localdomain ESMTP Postfix
HELO example.com
250 localhost.localdomain
MAIL FROM: user@example.com
250 2.1.0 Ok
RCPT TO: root@smtp-test.local
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: test@example.com
Subject: test
Body test
.
250 2.0.0 Ok: queued as D73CF18808FB
QUIT
221 2.0.0 Bye
Connection closed by foreign host.
送られた側を見てみます。
# cat /var/spool/mail/root
From user@example.com Thu Nov 18 16:53:31 2021
Return-Path: <user@example.com>
X-Original-To: root@smtp-test.local
Delivered-To: root@smtp-test.local
Received: from example.com (unknown [192.168.56.1])
by localhost.localdomain (Postfix) with SMTP id D73CF18808FB
for <root@smtp-test.local>; Thu, 18 Nov 2021 16:52:59 +0900 (JST)
From: test@example.com
Subject: test
Body test
届いていることがわかります。
下準備2
gmail.comのメールをリレーするようにします。
# sed -i s/^#relay_domains\ =\ \$mydestination/relay_domains\ =\ \$mydestination,\ gmail.com/g /etc/postfix/main.cf
systemctl restart postfix
Virtualbox内のSMTPに接続してGmailのアドレスに送信
さきほどの3つを変えてみます。MAIL FROMは.jp、Fromはorgにしてみます。
ここでSPFがどのように判断されているか確認します。
HELO exmpale.com
MAIL FROM: user@example.jp
From: test@example.org
% telnet 192.168.56.101 25
Trying 192.168.56.101...
Connected to 192.168.56.101.
Escape character is '^]'.
220 localhost.localdomain ESMTP Postfix
HELO exmpale.com
250 localhost.localdomain
MAIL FROM: user@example.jp
250 2.1.0 Ok
RCPT TO: (yourname)@gmail.com
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: test@example.org
Subject: test
Body test
.
250 2.0.0 Ok: queued as 61DD418808F8
QUIT
221 2.0.0 Bye
Connection closed by foreign host.
gmailを見てみます。(迷惑メールに分類されていました)
注目はReceived-SPF
の部分です。
Delivered-To: (yourname)@gmail.com
Received: by 2002:(略) with SMTP id fh36csp194206ysb;
Thu, 18 Nov 2021 00:45:25 -0800 (PST)
X-Google-Smtp-Source: (略)
X-Received: by 2002:(略) with SMTP id v6-(略)mr64030887plz.15.1637225125151;
Thu, 18 Nov 2021 00:45:25 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; t=1637225125; cv=none;
d=google.com; s=arc-20160816;
b=(略)==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
h=subject:from:message-id:date;
bh=(略)=;
b=(略)==
ARC-Authentication-Results: i=1; mx.google.com;
spf=neutral (google.com: xxx.xxx.xxx.xxx is neither permitted nor denied by best guess record for domain of user@example.jp) smtp.mailfrom=user@example.jp
Return-Path: <user@example.jp>
Received: from localhost.localdomain ([xxx.xxx.xxx.xxx ])
by mx.google.com with ESMTPS id j64si4519585pge.37.2021.11.18.00.45.24
for <(yourname)@gmail.com>
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Thu, 18 Nov 2021 00:45:24 -0800 (PST)
Received-SPF: neutral (google.com: xxx.xxx.xxx.xxx is neither permitted nor denied by best guess record for domain of user@example.jp) client-ip=xxx.xxx.xxx.xxx;
Authentication-Results: mx.google.com;
spf=neutral (google.com: xxx.xxx.xxx.xxx is neither permitted nor denied by best guess record for domain of user@example.jp) smtp.mailfrom=user@example.jp
Date: Thu, 18 Nov 2021 00:45:24 -0800 (PST)
Message-ID: <619612a4.1c69fb81.daa42.e0fdSMTPIN_ADDED_MISSING@mx.google.com>
Received: from exmpale.com (unknown [192.168.56.1]) by localhost.localdomain (Postfix) with SMTP id 61DD418808F8 for <(yourname)@gmail.com>; Thu, 18 Nov 2021 17:44:32 +0900 (JST)
From: test@example.org
Subject: test
bodytest
SPFの判定結果はneutralとなっています。
Received-SPF: neutral (google.com: xxx.xxx.xxx.xxx is neither permitted nor denied by best guess record for domain of user@example.jp) client-ip=xxx.xxx.xxx.xxx;
どこのドメインを見ているか、というと「user@example.jp」となっていますので、HELOでもFromでもなく、MAIL FROMを見ていることがわかります。
Received: from exmpale.comとあり、HELOの値はここで使われていることがわかります。
example.jpのTXTレコードはグローバルに引けず、SPFの情報がないので、Neutralになってしまいます。(RFC上はSPFレコードが抽出できない場合は2.6.1のnoneに該当するはずですがなぜか2.6.2のNeutralになっています)
MAIL FROMをexample.comにした場合は、グローバルで引けるTXTレコードに "v=spf1 -all"
とありますので、SPFはFAILになります。
Received-SPF: fail (google.com: domain of user@example.com does not designate xxx.xxx.xxx.xxx as permitted sender) client-ip=xxx.xxx.xxx.xxx;
2.RFCをあわせてSPFの判定を見る
1.送信元を主張してメールを送る
HELO, MAIL FROMによって入力することができます。
RFC7208では、SPFにHELOとMAIL FROMのどちらかを使う、と書かれています。(利用する対象としては両方考えられる)
using a given "HELO" or "MAIL FROM" identity during a mail transaction.
2章-3のHELOの部分では、HELOのチェックはマストではなく、推奨と書いてあり、MAIL FROMが正しいだけでも良さそうです。
2. 送信元と騙られないようにSPFレコード(送信元として承認しているホスト)を設定する
自分のドメインを騙ってメールが送信されないように設定する値です。
送信元として許可するIPやMXレコードを指定し、最後に-all
を使って指定外の値からメールは送らない、とするのが一般的です。
場合によっては~all
として、Softfailとすることもあります。
3.受信者(MTA)が1.と2.の情報を組み合わせてSPFを確認する
Gmailの場合、SPFの判定に送信主が主張(入力)するMAIL FROMが使われることがわかりました。
1.のようにHELOも見るとRFCにはありますので、他の条件ではそちらも見る可能性があります。
よく言われるReverse DNSを設定する(メールサーバーのIPにMXと同じFQDNを逆引き設定しておく)ですが、こちらについてはRFC7208に記載が見当たらなく、このSPFの要請ではないようです。
ですが、送信元IPの逆引きができるものに関しては一般的にはReverse DNSが実行されメールヘッダに結果が出てきます。
参考資料
telnetでメール送信(ash.jp)
2021年11月18日現在
Email Authentication for Internationalized Mail
SPF [RFC7208]
DKIM [RFC6376]
DMARC [RFC7489]