先日久しぶりにメールの解析をしたのだが、結構忘れていることとか、理解が曖昧な部分があったので、メモ。
記事の最後にテスト用のメールサーバーのセットアップ方法も載せておく。
用語
SMTP
Simple Mail Transfer Protocol
メールクライアントからメールサーバーへのメール送信や、メールサーバー間でのメールの転送に使用されるプロトコル。
POP
Post Office Protocol
メールソフトがメールサーバーからメールを受信する際に使用されるプロトコル。
IMAP
Internet Message Access Protocol
こちらも、メールソフトがメールサーバーからメールを受信する際に使用されるプロトコル。
SPF
Sender Policy Framework
送信元のメールアドレスが他のドメイン名に詐称されていないか検出する技術。以下、ざっくり仕組み。
- ドメインの管理者は権威メールサーバーの一覧を記載したSPFレコードをDNSサーバーに登録する。
- メールサーバーは、メールを受信した際に送信元メールアドレスのドメインのSPFレコードを参照する。
- メールの送信元IPアドレスとSPFレコードに記載されているIPアドレスが一致した場合は、送信元メールアドレスは詐称されていないと見なす。
- メールの送信元IPアドレスとSPFレコードに記載されているIPアドレスが一致しない場合は、送信元メールアドレスを信頼できないと見なす。
SPFレコードはDNSのTXTレコードを参照することで確認できる。以下はhotmail.com
のSPFレコードである。
$ dig +short -t TXT hotmail.com
"google-site-verification=gqFmgDKSUd3XGU_AzWWdojRHtW3_66W_PC3oFvQVZEw"
"google-site-verification=VdfSHp3aOmiGxd6jcbkRPFy6EERzln_hMR3byLjU__w"
"v=spf1 ip4:157.55.9.128/25 include:spf-a.outlook.com include:spf-b.hotmail.com include:spf-b.outlook.com include:spf-a.hotmail.com include:_spf-ssg-b.microsoft.com include:_spf-ssg-c.microsoft.com -all"
v=spf1 ip4:157.55.9.128/25 include:spf-a.outlook.com include:spf-b.hotmail.com include:spf-b.outlook.com include:spf-a.hotmail.com include:_spf-ssg-b.microsoft.com include:_spf-ssg-c.microsoft.com -all
がSPFレコードに該当する。
DKIM
DomainKeys Identified Mail
電子署名を用いてメールを認証する技術。以下、ざっくり仕組み。
- メールの送信者は作成したメールの情報 (ヘッダーやメッセージボディ等)をハッシュ化して、秘密鍵で暗号化する。これが電子署名である。作成された電子署名はメールのヘッダーに付与される。
- 受信者のメールサーバーは、送信元メールアドレスのドメインのDNSレコードから公開鍵を取得して電子署名を復号し、ハッシュ値を取り出す。
- メールサーバーは受信したメールのハッシュ値を算出し、電子署名から復号したハッシュ値と比較する。両者が一致すればメールは改ざんされていないと見なす。
DKIMレコードから公開鍵を取得するには、以下の特殊なドメインのTXTレコードを参照する。
<selector>._domainkey.<domain>
<selector>
はDKIMのセレクターを表す。セレクターとは目当ての公開鍵を見つけるための識別子のようなもの。<domain>
は送信元メールアドレスのドメインを表す。
セレクターは受信したメールのDKIM-Signatureヘッダーから確認できる。以下は、DKIM-Signatureヘッダーの例。
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=h0g3fuga;
s=
で定義されているh0g3fuga
がセレクターである。
上記に対応する公開鍵を取得するには以下のドメインのTXTレコードを参照する。
h0g3fuga._domainkey.example.com
digコマンドで参照する場合:
dig -t TXT h0g3fuga._domainkey.example.com
DMARC
Domain-based Message Authentication, Reporting, and Conformance
SPFやDKIMによる認証に失敗したメールを、受信側のメールサーバーがどう取り扱うべきかをドメインの管理者が指定することが出来る技術。以下、ざっくり仕組み。
- ドメインの管理者はDMARCレコードをDNSサーバーに登録する。
- DMARCレコードにはSPFやDKIMによる認証に失敗したメールに対して、受信側のメールサーバーが取るべき対応が記載されている。大きく分けて
- none: 何もしないで、宛先アドレスまで配送
- quarantine: 迷惑メールフォルダに振り分ける
- reject: 受信拒否
- 受信側のメールサーバーは
_dmarc.<domain>
のTXTレコードからDMARCレコードを参照できる。
以下は、gmail.com
のDMARCレコードの例。
$ dig +short -t TXT _dmarc.gmail.com
"v=DMARC1; p=none; sp=quarantine; rua=mailto:mailauth-reports@google.com"
SPF vs DKIM vs DMARC
- SPFはメールの送信元IPアドレスをもとに送信元メールアドレスを認証する。
- DKIMは電子署名を用いてメールの内容が改ざんされていないか検証する。
- DMARCはSPFやDKIMによる認証に失敗したメールを、受信側のメールサーバーがどう取り扱うべきかをドメインの管理者が指定することが出来る技術。
Bounced Email
バウンスメール
何らかの理由でメールサーバーに受信拒否されたメールのこと。あるいは受信拒否されたことを送信者に伝えるメールのこと。
サンプルメール
テスト用のメールサーバーを立ち上げて、以下のsendemail
コマンド (sendmail
ではない)でメールを送信。
sendemail -u "This is John" -m "Hi! This is John." -t kali@example.com -f "John <george123@yahoo.com>" -o tls=no -o reply-to=michael456@gmail.com -a attachment.zip
以下が受信したメールのソース。
Return-Path: <george123@yahoo.com>
X-Original-To: kali@example.com
Delivered-To: kali@example.com
Received: from kali (localhost [IPv6:::1])
by kali.localdomain (Postfix) with ESMTP id 0C97F140CB1
for <kali@example.com>; Tue, 25 Mar 2025 09:44:12 -0400 (EDT)
Message-ID: <793776.452864648-sendEmail@kali>
From: "John" <george123@yahoo.com>
Reply-To: "michael456@gmail.com" <michael456@gmail.com>
To: "kali@example.com" <kali@example.com>
Subject: This is John
Date: Tue, 25 Mar 2025 13:44:11 +0000
X-Mailer: sendEmail-1.56
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----MIME delimiter for sendEmail-64224.0262395752"
This is a multi-part message in MIME format. To properly display this message you need a MIME-Version 1.0 compliant Email program.
------MIME delimiter for sendEmail-64224.0262395752
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hi! This is John.
------MIME delimiter for sendEmail-64224.0262395752
Content-Type: application/x-zip-compressed;
name="attachment.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="attachment.zip"
UEsDBAoAAAAAANNKeVrGNbk7BQAAAAUAAAAIABwAdGVzdC50eHRVVAkAAx6u4mceruJndXgLAAEE
6AMAAAToAwAAdGVzdApQSwECHgMKAAAAAADTSnlaxjW5OwUAAAAFAAAACAAYAAAAAAABAAAAtIEA
AAAAdGVzdC50eHRVVAUAAx6u4md1eAsAAQToAwAABOgDAABQSwUGAAAAAAEAAQBOAAAARwAAAAAA
------MIME delimiter for sendEmail-64224.0262395752--
以下は上記のメールをOutlookで開いたもの。

メールヘッダー
Subject
Subject: This is John
メールの件名を示す。
Message-ID
Message-ID: <793776.452864648-sendEmail@kali>
メールの識別子。
To
To: "kali@example.com" <kali@example.com>
メールの宛先アドレスを示す。
From
From: "John" <george123@yahoo.com>
メールの送信者を示す。上記の例だとJohn
が送信者の名前 (表示名)でgeorge123@yahoo.com
が送信者のアドレスを表す。
Fromヘッダーは詐称可能。送信者の名前とアドレスともに任意の値を設定できる。
解析のメモ:
- 送信者の表示名とアドレスに不自然な不一致はないか? (表示名は
John
なのにアドレスはgeorge123@yahoo.com
など)
Reply-To
Reply-To: "michael456@gmail.com" <michael456@gmail.com>
メールの返信先のアドレス。Fromヘッダーで指定したアドレスと異なるアドレスを返信先に指定することも可能。
Reply-Toヘッダーは詐称可能。返信先として任意の値を設定できる。
解析のメモ:
- FromヘッダーとReply-Toヘッダーのアドレスまたはドメインは一致しているか?(Fromのアドレスは
@yahoo.com
なのにReply-Toのアドレスは@gmail.com
など)
Return-Path
Return-Path: <george123@yahoo.com>
メールサーバーによって受信拒否されたメール (bounced email) の返送先として使用されるアドレス。
Return-Pathヘッダーは詐称可能。任意の値を設定できる。
解析のメモ:
- FromヘッダーとReply-ToヘッダーとReturn-Pathヘッダーのアドレスまたはドメインは一致しているか?不自然な不一致はないか?
Received
Received: from kali (localhost [IPv6:::1])
by kali.localdomain (Postfix) with ESMTP id 0C97F140CB1
for <kali@example.com>; Tue, 25 Mar 2025 09:44:12 -0400 (EDT)
メールが受信されるまでに経由したメールサーバーの情報を示す。上記の例だとReceivedヘッダーはひとつしかないが、実際のメール通信は複数のメールサーバーを経由することもあるので、Receivedヘッダーが複数付与される。その場合、一番下にあるReceivedヘッダーが大元の送信元を表す。Receivedヘッダーを下から上と確認することで、メール受信までの経路をたどることが出来る。
解析のメモ:
- Receivedヘッダーが複数ある場合は、一番下にあるReceivedヘッダーが大元の送信元を表す
- Receivedヘッダーを下から上と確認することで、メール受信までの経路をたどれる
X-Mailer
X-Mailer: sendEmail-1.56
メールを作成したメールソフトに関する情報を示す。上記の例だとメールの作成にsendEmailが用いられたことが分かる。オプションのヘッダーなので付与されていない場合も多い。
Content-Disposition: attachment
Content-Disposition: attachment; filename="attachment.zip"
UEsDBAoAAAAAANNKeVrGNbk7BQAAAAUAAAAIABwAdGVzdC50eHRVVAkAAx6u4mceruJndXgLAAEE
6AMAAAToAwAAdGVzdApQSwECHgMKAAAAAADTSnlaxjW5OwUAAAAFAAAACAAYAAAAAAABAAAAtIEA
AAAAdGVzdC50eHRVVAUAAx6u4md1eAsAAQToAwAABOgDAABQSwUGAAAAAAEAAQBOAAAARwAAAAAA
添付ファイルを示す。filename
フィールドはファイル名を示しており、ファイルはBase64エンコードされている。上記の例だとattachment.zip
というファイルがBase64エンコードされた状態で添付されている。デコードすることでファイルを抽出できる。

Authentication-Results
Authentication-Results: mx.google.com;
dkim=pass header.i=@gmail.com header.s=20210112 header.b=L1YMtp8D;
spf=pass (google.com: domain of hoge@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=hoge@gmail.com;
dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com
DKIM、SPF、DMARCなどの認証の成否が保持されている。上記はすべての認証チェックをパスしたことを示している。
逆に以下は認証に失敗した場合の例。
authentication-results: spf=fail (sender IP is 1.2.3.4)
smtp.mailfrom=example.com; dkim=none (message not signed)
header.d=none;dmarc=fail action=quarantine
header.from=example.com;compauth=none reason=451
SPFとDMARCの認証に失敗している。またdkim=none
より、DKIMが使用されていないことが分かる。
解析のメモ:
- Authentication-Resultsの結果がfailの場合、信頼できない送信元からメールが送信された可能性が高い。Fromヘッダーなども詐称されている可能性がある。
Received-SPF
Received-SPF: pass (google.com: domain of hoge@gmail.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41;
SPFの詳細情報を示す。上記の例だとメールがgmail.com
の正規のメールサーバーから送信されたことが分かる。
逆に以下はSPFに引っかかった場合の例。
received-spf: Fail (protection.outlook.com: domain of example.com does not
designate 1.2.3.4 as permitted sender) receiver=protection.outlook.com;
client-ip=1.2.3.4;
上記の例は、example.com
のメールサーバーとして許可されていないIPアドレスからメールが送信されたことを示している。
解析のメモ:
- Received-SPFの結果がFailの場合、信頼できない送信元からメールが送信された可能性が高い。Fromヘッダーなども詐称されている可能性がある。
Kali Linuxにテスト用のメールサーバーをセットアップする
Postfixをインストール。
sudo apt-get update
sudo apt-get install postfix
/etc/postfix/main.cf
をバックアップする。
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
/etc/postfix/main.cf
を編集する。
送信用のドメインはmyorigin
で定義されている。
# Which domain that locally-originated mail appears to come from.
# Debian policy suggests to read this value from /etc/mailname.
#XX needs a review in postinst&config
#myorigin = /etc/mailname
#myorigin = $mydomain
myorigin = $myhostname
受信用のドメインはmydestination
で定義されている。
# List of domains (maptype:mapname allowed) that this machine considers
# itself the final destination for.
mydestination = $myhostname, kali, localhost.localdomain, , localhost, example.com
本メールサーバーの中継を許可するSMTPクライアントはmynetworks
で定義されている。検証目的の場合は (踏み台としての利用を阻止するためにも)内部ネットワークのアドレスを定義するに留めておく。
# List of "trusted" SMTP clients (maptype:mapname allowed) that have more
# privileges than "strangers". If mynetworks is not specified (the default),
# mynetworks_style is used to compute its value.
#mynetworks_style = class
#mynetworks_style = subnet
mynetworks_style = host
#
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
設定が完了したら、Postfixを起動。
sudo postfix status
sudo postfix start
テストメールを送信。
sendemail -u "Test mail" -m "This is test mail" -t kali@example.com -f hoge@exmaple.com -o tls=no
受信したメールは/var/mail/<username>
から確認できる。
└─$ cat /var/mail/kali
From hoge@exmaple.com Fri Mar 28 09:53:33 2025
Return-Path: <hoge@exmaple.com>
X-Original-To: kali@example.com
Delivered-To: kali@example.com
Received: from kali (localhost [IPv6:::1])
by kali.localdomain (Postfix) with ESMTP id 6AE01140C22
for <kali@example.com>; Fri, 28 Mar 2025 09:53:33 -0400 (EDT)
Message-ID: <43127.0532749011-sendEmail@kali>
From: "hoge@exmaple.com" <hoge@exmaple.com>
To: "kali@example.com" <kali@example.com>
Subject: Test mail
Date: Fri, 28 Mar 2025 13:53:33 +0000
X-Mailer: sendEmail-1.56
MIME-Version: 1.0
Content-Type: multipart/related; boundary="----MIME delimiter for sendEmail-938435.28775415"
This is a multi-part message in MIME format. To properly display this message you need a MIME-Version 1.0 compliant Email program.
------MIME delimiter for sendEmail-938435.28775415
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
This is test mail
------MIME delimiter for sendEmail-938435.28775415--