LoginSignup
3
2

More than 1 year has passed since last update.

【学習メモ】SPFが正しく設定されるかSMTPコマンドを実行して見分ける

Last updated at Posted at 2021-11-18

0.要約

SPFは以下3つの登場人物の組み合わせによるもの。

  1. メールの送信者(正規の送信者、Amazon SESなど代理の送信者、スパムメール業者など)
  2. ドメインの持ち主(メール送信元とされる)
  3. メールの受信者

それぞれが実際にやること。

  1. 送信元を主張してメールを送る → HELO, MAIL FROM(Return-Path/エンペローブID)に含まれるドメイン
  2. 送信元と騙られないようにSPFレコード(送信元として承認しているホスト)を設定する
  3. 受信者(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]

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2