2013年にVPSを契約しメールサーバーを立ち上げて以来,私のメインのメールアカウントは自前のものを使用している。大きなトラブルもなく,ほぼ期待通りの運用ができた。しかし,多少の問題点もあった。それは,hotmailへのメールが迷惑メールとして分類されることであった。
hotmailのアカウントを持っている知人にメールを出したことがあった。返事が無いので,直接聞いてみると,「届いてない」とのこと。「変だな?」と思って,更に調べてもらったところ,「届いていはいたが,迷惑メールに分類されていたので,読まなかった」とのことであった。私もhotmailにアカウントを持っているので,試しにhotmailの自分宛てに出してみたところ,やっぱり迷惑メールに分類されていた。私の個人的なメールアドレスは世界中で私しか使わないメールサーバー名なので,勿論,馴染みのないものである。そのことから,怪しいと判断されて,迷惑メールとされたのだろうと考え,以後,hotmail宛てにメールを出すときには,hotmailのアカウントを利用することにしている。
昨年末,CentOS8,そしてOracle Linux8をインストールするときに,迷惑メールと分類されない対策として,SPFとDKIMという方法があることを知った。そこで,今回はこれらの対策を講じることにした。また,これらの設定を行っている中で,それらを利用した,迷惑メール対策の技術として,DMARCについても知った。これについても試してみることにした。
SPF
SPF(Sender Policy Framework)については
https://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/spf/
に詳しい説明がある。SPFは送信元が指定したIPアドレス等から実際にメールが送信されていたかどうかの検証を行う。そのために,送信元メールアドレスのドメインのDNSに,送信に使うサーバーのIPアドレス情報を記載する。受信サーバーは,受信したメールアドレスのドメインのDNSを参照して,送信IPアドレス等の情報を取得し,実際に送信してきたサーバーのIPアドレス等がそれに一致するかどうか検証を行う。例えば,このpearlblue.netからのメールの場合,pearlblue.netのDNSサーバーに,送信メールサーバーのIPアドレスを登録する。具体的には,
v=spf1 +ip4:157.7.140.107 -all
をpearlblue.netのDNSのTXTリソースレコード(TXT RR)に登録する。(本来はSPF RRに登録するものだが,現時点では,SPF RRをサポートしていないDNSでは,TXT RRを使うことも認められている。)上の記述は3つの部分からなっている。v=spf1は以下がSPFのバージョン1で記述されていることを示す。+ip4:157.7.140.107はip4:157.7.140.107が送信サーバーのipv4でのIPアドレスであることを示す。-allはそれ以外は送信サーバーでないことを示す。このように設定し,pearlblue.netから,メールを送信し,それを受信したメールのソースに,
Authentication-Results: spf=pass (sender IP is 157.7.140.107)
とあれば,設定は成功したことになる。
DKIM
DKIM (Domainkeys Identified Mail)は,電子署名を用いて,送信元ドメインを検証する方法である。これについては,
https://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/dkim/
に詳しい説明がある。送信側では,まず,DNSで,送信元ドメインの公開鍵を公開する。さらに,個々のメールの送信時には,次の処理を行う。メール本文を正規化等の処理を施し,それらのハッシュ値に対して署名を行い,それをメールに追加し,送信する。受信側では,送信元ドメインのDNSで公開鍵を取得し,その公開鍵を利用して,メール本文から得られるハッシュ値と署名を照合し検証する。これにより,送信元の偽装だけでなく,本文の改変もチェック可能となる。
DKIM署名を行うツールとして,opendkimを使った。opendkimを利用したDKIM署名については,本家opendkim.orgの他,日本語による説明のwebページもいくつかある。本サイトの設定でもそれら説明を利用させていただいた。
DKIMの設定手順は以下の通りである。
- キーペアの作成
- 公開鍵等のDNSでの公開
- opendkimの設定
- MTAの設定
1.キーペアの作成
署名用の公開鍵(public key)と秘密鍵(private key)を作成する。本サイトでは,複数のバーチャルドメインを利用しているので,各ドメインごとにキーペア作成した。そのために各ドメインごとの鍵用ディレクトリを
/etc/opendkim/keys/
以下に作成し,そこに保存する。例えば,pearlblue.net用には,
mkdir /etc/opendkim/keys/pearlblue.net
と作成する。この後,例えば
opendkim-genkey -D /etc/opendkim/keys/pearlblue.net/ -d pearlblue.net -s 鍵ファイル名
とすれば,鍵ファイル名.privateと鍵ファイル名.txt(公開鍵)というpearlblue.net用の鍵が,/etc/opendkim/keys/pearlblue.net/以下に作成される。
ここで,opendkim-genkeyのオプションは,-Dはディレクトリ,-dはドメイン,-sはセレクター(鍵ファイル名)を示す。
2.公開鍵等のDNSでの公開
署名用の公開鍵は,各ドメインのDNSで公開する。例えば,pearlblue.netであれば,鍵ファイル名._domainkey.pearlblue.netのDNSのTXTリソースレコードに
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7cVqgPoFackGkJOLJNjFKjSvEUyXh8Z6Wedx7P44WuHgZDh29Gk6Ujk2tk3dZ1/fZKt7xkDDZ5IQCqcwbWJ/SroOhtMyTICR92EoDwQ8NvsfK4R9ZWwx779PMClElO+eJWNH3n5efQhvJd2UzcCGTYsPSbZ3Amwc1fwM9PrWxEwIDAQAB
等と記述し,公開鍵を公開する。更に,ADSP(Author Domain Signing Practices)レコードも公開する。これはDKIMの認証結果の扱いを指定するもので,_adsp._domainkey.<ドメイン名>で公開する。例えば,pearlblue.netの場合では,_adsp._domainkey.pearlblue.netのDNSのTXTリソースレコードに
dkim=unknown
を記述した。この値 unknown の意味は,「このドメインから送信されるメールのいくつか,またはすべてに,メール作成者署名が与えられる」を示している。unknown以外の値もあるが,普通はこの値が推奨されている。
3.opendkimでの設定
署名を追加するために,/etc/opendkim.conf の設定を行う。Defaultから変更したところは以下の通り。
- Mode sv
- KeyTable /etc/opendkim/KeyTable
- SigningTable refile:/etc/opendkim/SigningTable
- ExternalIgnoreList, InternalHosts
・Mode sv
sは送信メールに署名を追加,vは受信メールの検証を行う。
・KeyTable
複数のバーチャルドメインに対応するため,KeyTableを使う。KeyTableには各ドメインのKeyFileの名前と場所を
default._domainkey.example.com example.com:default:/etc/opendkim/keys/default.private
の形式で列挙する。
・SigningTable
複数のバーチャルドメインに対応するため,SigningTableを使う。各ドメインのKeyFileの名前を
*@example.com default._domainkey.example.com
の形式で列挙する。
・ExternalIgnoreList, InternalHosts
これらはいずれも,TrustedHosts(今の場合は,自ホスト127.0.0.1)と設定した。
4.MTAの設定
opendkimはMilter(Mail Filter)として動作するので,MTA側にその設定を行う。本サイトでは,MTAとして,postfixを使うので,対応して,/etc/postfix/main.cfの設定を行う。postfixでのMilterの取り扱いについては,http://www.postfix-jp.info/trans-2.3/jhtml/MILTER_README.htmlに説明がある。その説明を参考にして,opendkim.confでのsocket番号設定8891に従って,/etc/postfix/main.cfの最後に
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
と設定した。意味は,「smtp及びそれ以外のプロトコルでのメールのMilterとしてopendkimを使う。Milterにエラーがあった場合,Milterが無かったように振る舞う。」である。このように設定した後,postfixとopendkimを再起動すれば良い。その後,DKIM対応サーバー宛てに送信したメールを受信したサーバーで読んだとき,そのヘッダに,
dkim=pass (signature was verified) header.d=pearlblue.net
とあれば,設定は成功したことになる。
DMARC
DMARC(Domain-based Message Authentication, Reporting, and Conformance)はRFC 7489で規定されている,SPFとDKIMを組み合わせ,なりすましメールを防ぐ方法である。これについては
https://support.google.com/a/topic/2759254?hl=ja&ref_topic=9061731
や,他のwebページに多くの説明がある。SPFとDKIMを導入しているドメインからのメールがSPFとDKIMをパスしなかった場合は,そのメールは,送信元を偽装しているか,送信側で何らかの不具合があったことを意味している。そのようなメールに対して,どのような処理をするか送信元(とされる)ドメインが決めることができる仕組みである。送信元ドメインは,_dmarc.送信元ドメインのDNSのTXT RRにその方針を記述し,公開する。受信サーバーでは,送信元ドメインの_dmarc TXT RR を参照して,その処理を行う。
例えば,pearlblue.net では,まず,準備としてレポート受取用アドレスdmreport@pearlblue.netを作成した。更に,_dmarc.pearlblue.net のDNSにTXT RRとして,TTL=3600で値
v=DMARC1; p=none; pct=100; rua=mailto:dmreport@pearlblue.net; ruf=mailto:dmreport@pearlblue.net
と設定した。ここで,「vはバージョンを示し,DMARC1を指定。p(policy)は処理法を示し,noneはメールをそのまま受信者に配信して、日次レポートに記録する。pctは処理対象のメールの割合を示す。100は100%すべてのメールに対して,pの処理を施す。ruaはドメインの DMARC認証の結果に関するレポートを受け取るメールアドレス。rufは認証が失敗したもの関するレポートを受け取るメールアドレスである。
このように設定した後,DMARC対応サーバー宛てに送信したメールを受信したサーバーで読んだとき,そのヘッダに,dmarc=passとあれば,設定が成功したことになる。試しにhotmail宛てに送ってみた結果は次の通りであった。
Authentication-Results: spf=pass (sender IP is 157.7.140.107)
smtp.mailfrom=pearlblue.net; hotmail.co.jp; dkim=pass (signature was
verified) header.d=pearlblue.net;hotmail.co.jp; dmarc=pass action=none
header.from=pearlblue.net;compauth=pass reason=100
このメールは迷惑メールに分類されず,普通の受信Boxに入っていた。成功したようだ。