Rspamdを使って送信ドメイン認証の認証済み受信チェーン Authenticated Received Chain (ARC)を導入する

メールを届ける
©いらすとや.

お仕事でメールサーバを管理・運用するような人には「がとらぼ」は用無しで、メールサーバを管理・運用しない人には全く興味がないかもしれないけど、送信ドメイン認証関連でARCのこと。

  • SPF: メールの送信元MTAのIPアドレスとDNSのSPFレコードに書かれたIPアドレスを比較検証
  • DKIM: 送信側MTAで電子署名を付け、受信側はDNSの公開鍵を取得して検証
  • DMARC: 送信者ドメイン認証に失敗(正当ではない送信者)の場合にメールの破棄等をリクエスト+レポート
  • ARC: 認証の連鎖でメールヘッダを投稿者まで辿る

それぞれ役割が異なるのでどれを導入すれば良いとかじゃなくて全部入れたいところ。SPFだけ、DKIMだけ或いはSPF + DKIMだけというのはできるけど、DMARCだけとかARCだけというのは無い。
で、SPFやDKIMは、メーリングリストや代理送信等では認証がFailする。DMARCのポリシーがRejectだとそのメールが受信側MTAで破棄される可能性がある。(でも、DMARCのポリシーは「何もしない」ではなく厳しく「Reject」にしたいところ。でないと導入の意味が半減だと思う。)

今回のARCは経路のMTA(メーリングリストのような中間・再送信サーバ等も)で検証を行い検証の数珠つなぎを行う。送信・再送信・受信サーバの全てがARC対応ならだけど。
そして、ARCでの認証がPassならDKIM認証がFailでも送信認証PassとすることでSPF, DKIMの中間・再送信サーバ問題も解決できる(かもしれない)。
「がとらぼ」の中の人が運用しているMTAではすでにDMARCをRejectポリシーで運用しているのでARCには対応したいところ。

大手でも既にGmailは(受信側は)ARC対応している。
送信側で対応しているところを知らないが。

簡単にやりたいので迷惑メール対策ツールのRspamdのarcモジュールを使用する。

https://rspamd.com/doc/modules/arc.html と modules.d/arc.conf を参考に設定する。ウェブの設定例は複数の書き方が混ざってるので不慣れだと混乱させられる。

設定するファイルは local.d/arc.conf (無ければ新規作成)。modules.d/arc.confは変更しないこと。
基本的には上のリンクのページの真似で良いんだけど、秘密鍵のpathを既に設定している筈のDKIMのものと同じにする又はコピー又はシンボリックリンクにするとラク。この方法では、ARCとDKIMで同じ秘密鍵を使うけど、ちゃんとDKIM署名とは別のARC用の署名になる。
設定項目の秘密鍵の path の書き方は複数ある。(既にある)DKIMの設定(local.d/dkim_signing.conf)を真似ると簡単。
これだと(DKIM用の秘密鍵をARCでも使うなら)、DNSに新たに公開鍵のTXTレコードの追加が不要。

もちろん、ARC用にDKIMと同じ方法で別の鍵のペアを作ってそれをARC専用として登録することもできる。筋としてもこちらが正当?ただし、先にDNSにARC用の公開鍵を登録してDNSを再起動し、REFRESH時間(できれば2倍)を待ってからMTAでARCを有効な状態にしてやらないと送信したメールがひどい目に合うかも。

管理者の世界ではセカンダリDNSまたは更に他所のDNSの古いキャツシュ消えるまで庚申待の宴を夜を明かして行うことになっています。

今回は一応DKIM用とは別にARC用の鍵のペアを用意することにする。(オススメはARC用を別途作らずDKIM用の流用の方)
DKIMの鍵の作り方は前回も書いたけど、下のようなの。(鍵ファイルを置くディレクトリはARC用に /var/db/rspamd/arc とする)

# mkdir /var/db/rspamd/arc
# rspamadm dkim_keygen -d example.com -s セレクタ -b 2048 -k /var/db/rspamd/arc/example.com.セレクタ.key > /var/db/rspamd/arc/example.com.セレクタ.pub

上の例の「セレクタ」の部分は共通の任意の文字列(半角英数字)を指定する。ARC専用に作るならDKIM用とは違うセレクタを指定する。 これで、 /var/db/rspamd/arc に example.com.セレクタ.pub (公開鍵)と example.com.セレクタ.key (秘密鍵)の2つのファイルが作成される。
Rspamdに登録するのは example.com.セレクタ.key (秘密鍵)の方。
example.com.セレクタ.pub (公開鍵)の内容(セレクタを含むドメインキー)をDNSの example.com 用ゾーンファイルに書く。

RSAで鍵長に2048bitなどを指定すると公開鍵が255文字を超える。rspamadm dkim_keygen が出力する公開鍵は予めDNSのTXTレコード用に行分割形式になってるが、それでも古いシステムのMTAを相手にすると問題になることもあるようなので注意。まぁそんな古いシステムを動かしているようなところならそもそもARC非対応だと思うのでおそらく何も考えずにコピペでOK

公開鍵は先のコマンドで出力した /var/db/rspamd/arc/example.com.セレクタ.pub のファイルの中身すべてをそのままDNSのゾーンファイルにコピペする。
arc._domainkey IN TXT ( "v=DKIM1; k=rsa; "
        "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqcOxgk+SkMRDo5Tj6e5HfVINHBRfEm6eaTDJp8L8aa+u15ueLEqyA3SBmWdistFVSAdSL8/MjBuogwpBvEJoQ23IhcITVIcwAsbYLMzFq6N1pJlQ3JqKF/127vjd13FFqAH9kbiasNOr1VIyt2namokz2CeM4js+IIk/yqF4Y2z6kSdHTofjzOhilsMpMAGNTa5Fh4OVEzDSL9sI7"
        "zH4YqxmGrqPVxDMUF4MF6XvR9HYlB1KApxsB4oAjcTGj3FwTzwroKG0QHCDETBEknuDJR51Ctpkrf3qO605TEWQlfe+c+2C3pNGh8IGDz5GkE4HqFKnr1jJX0R213adJAGe7QIDAQAB"
) ;

こんなの。この例ではセレクタを arc にしている。
DNSのTXTレコードは一応255文字までということになっているけど、括弧を使った複数行記述により255文字超えに対応している。DNSがBINDならDNSのゾーンファイルにそのままコピペ。BIND以外なら修正が必用かも。シリアルを増やすのを忘れずに。
rndc reload とか何かやってDNSの設定変更を反映させる。

ちなみにDKIMと同じようにRSAの他にEd25519で鍵を作って同じように配置してみたが、(少なくともRspamdの)ARCでは複数署名には対応していないっぽい。試した限りではRSAの署名しか使われなかった。まぁ経路内のMTAがEd25519非対応で検証のチェーンが切れてFailでは話にならないのでRSAだけで良いかもしれないが、これから普及させようというならいっそEdDSAな署名で統一すれば良かったのに。ARCの仕様でこのあたりどうなっているのか調べてないのでスミマセン。

今回はRspamdのサービス再起動ではなく、設定リロードを行う。

# service rspamd reload

これだけで、メール受信時のARC認証と、メール送信時のARC署名の両方を行ってくれる。postfixなどMTAには特に設定変更は不要なのがありがたい。

メールを送信して確認

自分宛に送ってみたメールのメールヘッダを見てみた。
確認するのは ARC-Message-Signature と ARC-Seal と ARC-Authentication-Results の3つと、最終的な送信認証結果であるAuthentication-Results (Rspamdの場合)の計4つのレコード。

ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=intaa.net;
	s=arc202010; t=1603108555;
	h=from:from:sender:reply-to:subject:subject:date:date:
	 message-id:message-id:to:to:cc:mime-version:mime-version:
	 content-type:content-type:
	 content-transfer-encoding:content-transfer-encoding:
	 in-reply-to:in-reply-to:references:references;
	bh=6VsBFBqz1cYAm4jEi75leHazQTFMa4BrcqUiEhaBfiE=;
	b=F0Ua28oi7jvsxqxxxe5dxEjL3Q8Dc8y5RqDHeqB0LxPnUL9OT3Qrk2vXYKuq+Zvi3pbXA1
	Y4sXM0i8JnLPlNhFfRkhiOOTh1b5a9UXxiH/nmqj0VopWWZ3H2Jc/v75N5Cp7U3PILiuOu
	2xp8biheXaTqj81FRyFeASQrEw+qBsazbkakfmYMuj0ESwEaIv/qCovalPbuDDQQEk3q3O
	PTH8AGTzv3NJf8eK+bA3fjMyAetV9gFr8S92SHc7Fy76sfzWF0pPBxu+lLTJani9cC68NP
	7Xk1fs7GtscR8+RBi/B5ZceCvvPgz4UbDYiTO3fb74YUxS3TninspYn38E+/fw==
ARC-Seal: i=1; s=arc202010; d=intaa.net; t=1603108555; a=rsa-sha256;
	cv=none;
	b=EYgwd/GZVS5StCJt007Srx9ivY4nIeL7Q6NV5nYt3JOYJF3UeAc81i0RIqbHCYfzLrcJQn
	YaKOswyF0dnTnkOnB0wEidrcR8tlWemIpFKN/pCnYXcZg+X+2K/HjMyNdVRWzVibR58rQm
	s/q4lXZL+wx82iw6BApKQJ7DYY0xm9z663gZR5kIn4AnVtKMTcziTrek1seCsIXbrimd6h
	hTvQmFa4abYIw4qdMLRMYNozu8bG4pUA4oqCIk3c92sMCbW2PGJSrzufbl5gz5doxjXLZK
	Zopcw6UcyQLHupOBvWP3ioylFF+e1yzD08oVsqm8sNHHN80LtOqHqmEnqTIy2g==
ARC-Authentication-Results: i=1;
	mail.intaa.net;
	auth=pass smtp.auth=gato@intaa.net smtp.mailfrom=gato@intaa.net
Authentication-Results: mail.intaa.net;
	auth=pass smtp.auth=gato@intaa.net smtp.mailfrom=gato@intaa.net
Gmailにメールを送ってみた (変更前)
Authentication-Results: mx.google.com;
	dkim=pass header.i=@intaa.net header.s=dkim header.b="P5dq/EPh";
	dkim=neutral (no key) header.i=@intaa.net header.s=eddsa header.b=s4PatVO3;
	arc=fail (DNS record missing);
	spf=pass (google.com: domain of gato@intaa.net designates 2001:2c0:d800:6701::2000 as permitted sender) smtp.mailfrom=gato@intaa.net;
	dmarc=pass (p=REJECT sp=NONE dis=NONE) header.from=intaa.net

中途半端な設定だったので、arc=fail で検証失敗しDNSに適切な公開鍵が無いと書かれている。
ARC-Authentication-Resultsも当然無い。
ちなみにdkimがpassとneutralの2つがあるのはDKIM用にRSAとEd25519の2種類の署名を用意しているから。GmailはEd25519非対応のようなのでそれがneutral (no key)になっている。(DKIM検証結果は次も同じ)

Gmailにメールを送ってみた (ARC設定後)
ARC-Authentication-Results: i=2; mx.google.com;
       dkim=pass header.i=@intaa.net header.s=dkim header.b="P5dq/EPh";
       dkim=neutral (no key) header.i=@intaa.net header.s=eddsa header.b=s4PatVO3;
       arc=pass (i=1);
       spf=pass (google.com: domain of gato@intaa.net designates 2001:2c0:d800:6701::2000 as permitted sender) smtp.mailfrom=gato@intaa.net;
       dmarc=pass (p=REJECT sp=NONE dis=NONE) header.from=intaa.net
Authentication-Results: mx.google.com;
       dkim=pass header.i=@intaa.net header.s=dkim header.b="P5dq/EPh";
       dkim=neutral (no key) header.i=@intaa.net header.s=eddsa header.b=s4PatVO3;
       arc=pass (i=1);
       spf=pass (google.com: domain of gato@intaa.net designates 2001:2c0:d800:6701::2000 as permitted sender) smtp.mailfrom=gato@intaa.net;
       dmarc=pass (p=REJECT sp=NONE dis=NONE) header.from=intaa.net

このレコードはメールの受信側であるGmailのmx.google.comが付けたもの。(ARCでは同じようなヘッダが並ぶので見るところを間違えないように)
arc=pass になって(受信側の)ARCによる検証成功。
このとき、 i=1 と i=2 でそれぞれ ARC-Seal, ARC-Message-Signature, ARC-Authentication-Resultsが存在する。中間サーバがあればさらに?

あとは、外部からARC付きメールを受信したときの動作確認をしたいところだけど、ARC付きでメールを送ってくれるところを知らないという・・

ARC署名付きのメールを送って下さった方がいたので署名を基に判断するという動作の確認ができました。チェーンの部分は(「がとらぼ」の人が理解できてないので)よく解らなかったけど。