いまさらだけど遅すぎというほどでもないDMARC レポート編1

前回はDMARCの設定の内メールの送受信に関わる部分しか触っていないので、今回はレポート周り。
これをやらないとDMARCを導入する意味がないとまでは言わないけど大切。

データベースの準備

まず、データを溜めるためのデータベースの準備。今回はMySQLを使うことにする。

# mysql -u root -pパスワード mysql  ←MySQLの管理者rootとそのパスワード
mysql> CREATE DATABASE opendmarc;
mysql> GRANT ALL PRIVILEGES ON opendmarc.* TO 'dmarc'@'localhost' IDENTIFIED BY 'opendmarc_db_password';
mysql> FLUSH PRIVILEGES;   ←GRANTでアカウント作るなら要らないんだっけ?行っても害はないのでやっておく
mysql> quit

opendmarcというDBとその全権限ユーザーdmarc、パスワードopendmarc_db_passwordを指定。localhostだけアクセス可。
DB名は下のファイルで指定されているのでopendmarcにしている。気に入らないなら下のファイルも要変更。

opendmarcにMySQL用のデータベース定義用(スキーマ)ファイルが付属しているのでそれを利用する。
FreeBSDの ports/pkg でopendmarcをインストールしたなら /usr/local/share/doc/opendmarc/schema.mysql がそれ。
ファイルの中で指定されているDB名がopendmarcになっている。

# mysql -u dmarc -popendmarc_db_password opendmarc < /usr/local/share/doc/opendmarc/schema.mysql
/usr/local/etc/mail/opendmarc.conf (変更)
1
2
3
HistoryFile /var/run/opendmarc.dat             #← 行頭の#を削除
HistoryFile /var/run/opendmarc/opendmarc.dat   #← もしくは場所としてはこっちのがいいかも
ReportCommand /usr/local/sbin/sendmail -t

レポート作成用のスクリプトとして GitHubGistからstevejenkins/opendmarc-send-reports.sh を貰って必要に応じて編集する。

/usr/local/etc/mail/opendmarc-send-reports.sh (FreeBSD用に変更)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/sh    #←オリジナルはbash
# Imports data from OpenDMARC's opendmarc.dat file into a local MySQL DB
# and sends DMARC failure reports to domain owners.
# Based on a script from Hamzah Khan (http://blog.hamzahkhan.com/)

set -e

# Database and History File Info
DBHOST='localhost'
DBUSER='dmarc'
DBPASS='opendmarc_db_password'
DBNAME='opendmarc'
HISTDIR='/var/run/opendmarc'
HISTFILE='opendmarc'  #←拡張子は書かない

# Make sure history file exists
touch ${HISTDIR}/${HISTFILE}.dat

# Move history file temp dir for processing
mv ${HISTDIR}/${HISTFILE}.dat /tmp/${HISTFILE}.$$

# Import temp history file data and send reports
/usr/local/sbin/opendmarc-import -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose < /tmp/${HISTFILE}.$$
/usr/local/sbin/opendmarc-reports -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose -interval=86400 -report-email 'postmaster@example.com' -report-org 'EXAMPLE.COM'
/usr/local/sbin/opendmarc-expire -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose

# Delete temp history file
rm -rf /tmp/*.$$
# chmod +x /usr/local/etc/mail/opendmarc-send-reports.sh
# touch /var/run/opendmarc/opendmarc.data
# chown postfix:vmail /var/run/opendmarc/opendmarc.data  #←/etc/rc.confに書いたopendmarc_runasに合わせる
# chmod 600 /var/run/opendmarc/opendmarc.data

opendmarc-send-reports.sh は実行可能にパーミッション変更。
/var/run/opendmarc/opendmarc.data は作成しておかないと(作成できないと) opendmarc が利用不可になるので注意。

# /usr/local/etc/rc.d/opendmarc restart

opendmarcを再起動。
DMARC対応ドメインからメール着信後に /var/run/opendmarc/opendmarc.dat のサイズが0でなくなることを確認。テキストファイルなので表示してみるのもあり。

# /usr/local/etc/mail/opendmarc-send-reports.sh

実行してエラーにならないことを確認。
opendmarc-import, opendmarc-reports, opendmarc-expire がそれぞれ複数行表示されること。
opendmarc-reports: sent report for hoge@example.com (2.0.0 Ok: queued as ABCDEF01234) のような行が1行以上あることを確認。

問題ないようであれば毎日自動実行されるようにする。

/etc/crontab
16  0  *  *  *  root  /usr/local/etc/mail/opendmarc-send-reports.sh > /dev/null 2>&1

例: 毎日夜中0:16に実行をcrontabに設定。

受信一覧レポートをウェブで確認

GitHubの techsneeze/opendmarc-dashboard に OpenDMARC Dashboard という極めて簡単でシンプルなPHPスクリプトがあるので貰ってくる。統計を作る機能など複雑なのは一切無し。単純に受信したメールのリストと送信ドメイン認証の結果とDMARCのポリシーが表示される。
opendmarc-dashboard-config.php.sample と opendmarc-dashboard.php をPHPが利用可能なウェブサイトのドキュメントルート下のどこかに置く。(今回はウェブサーバがopendmarcの動くメールサーバと同一とする)
opendmarc-dashboard-config.php.sample を opendmarc-dashboard-config.php にリネームするか opendmarc-dashboard-config.php にコピーする。 opendmarc-dashboard-config.php を編集。

/usr/local/www/hoge/hage/opendmarc-dashboard-config.php
1
2
3
4
$dbhost="localhost";
$dbname="opendmarc";
$dbuser="dmarc";
$dbpass="opendmarc_db_password";

上の方で指定したDMARC用のDBの情報に合わせる。

ブラウザで https://example.com/hoge/hage/opendmarc-dashboard.php を開く。初期値では最大で90行まで表示される。
たとえば256行表示させたい場合は https://example.com/hoge/hage/opendmarc-dashboard.php?limit=256 などとする。
ここに表示されるのは先の opendmarc-send-reports.sh の中の opendmarc-import によりデータベースにに登録された分だけ。なので情報はリアルタイムに更新(追加)されるわけではないので勘違い無く。

OpenDMARC Dashboard

ところで他所様のドメインのメールサーバー宛に送信するレポートメールの確認はどうしましょう?は以下のようなの。

facebookmail.comからUndelivered Mail Returned to Senderになってレポートメールが返送されてきたので正常に送信されていることが判った。っていうか、指定されてるメールアドレスにレポート送ってるのに叩き返すってどういうことよ。
他所に送信しているレポートのコピーが欲しければopendmarc.confのFailureReportsBccに希望のメールアドレスを指定したら届くのかな。

Subject: 
Report Domain: facebookmail.com Submitter: EXAMPLE.COM Report-ID: facebookmail.com-1509202920@EXAMPLE.COM
From: 
postmaster@example.com
Date: 
2017年10月29日 00:02
To: 
postmaster@facebook.com

This is a DMARC aggregate report for facebookmail.com
generated at Sun Oct 29 00:02:01 2017

添付ファイル: EXAMPLE.COM!facebookmail.com!1509116520!1509202920.zip
添付ファイルの中身はここには出さないけどXML形式のレポートファイル

DMARCを導入して運用すると(DNSの設定のDMARCの宣言でruaまたはrufを指定している場合)上のようなレポートメールが他所のDMARC運用ドメインから届いくようになる筈。次はその他所から届いたレポートメール(レポートファイル)を解析するのをやるつもり。

関連記事:

いまさらだけど遅すぎというほどでもないDMARC 導入編

この記事ではOpenDMRCを使っているが、迷惑メール対策でRspamdを利用しているならRspamdにもDMARCの機能があるのでOpenDMARCは使わずRspamdを使うのが良さそう。個別機能のmilterを一掃してRspamdを活用を参照。

毎日届く大量のメールのヘッダを見ると、まともなところはSPFやDKIMは導入しているみたい。でも、DMARC対応はそんなに多くはない印象。
せっかくDKIMまで対応しているならあとちょっと頑張ってDMARCにも対応したいところ。

  • SPF: 送信元のIPアドレスで正しい送信元を確認
  • DKIM: 送信するメールに電子署名してメールの詐称を確認
  • DMARC: 自分ドメインを詐称するメールの処理方法を指定・指定を受けて処理

DMARCは送信ドメイン認証のSPFやDKIMがあることが前提となる。送信ドメイン認証の結果を受けてどうして欲しいかというポリシーがDMARC。
つまり、「もし、オイラのドメインを送信元とするメールがあんたのメールサーバーに届いたとき、SPFやDKIMで調べて詐称だと判明したなら(何もしない|迷惑メール扱い|受け付けない)という扱いにしてね」と宣言するのがDMARC。
所有しているドメインを送信元とするメールが100%自分のところのメールサーバから送信されててDKIMの署名も確実に付いているということであれば「詐称したメールは受け付けなくてもいいよ」と宣言できるし、そうじゃないよということであれば「うちのメールサーバ以外から届いても迷惑メール扱いにしないでおいてね」と宣言しておいた方がいい。そういうもの。
ただし、MLとかも含めて考えると迂闊に「受け付けないで」にするのは怖いかも。

送信メールに関わる宣言側

DNSの設定に書き込む。以下はBINDの例。

1
2
3
4
5
6
7
$ORIGIN example.com.  ;1行目でoriginを宣言しているなら以下
;
;中略
;
                IN TXT "v=spf1 +ip4:192.168.0.0/24 +ip6:2001:db8::/32 +mx -all" ;これはSPFの例
hoge._domainkey IN TXT "v=DKIM1; g=*; k=rsa; p=ABCDEFG実際は超長い鍵0123456789"   ;これはDKIMの例
_dmarc          IN TXT "v=DMARC1; p=none; sp=none; ri=3600; rua=mailto:postmaster@example.com;   ruf=mailto:postmaster@example.com"  ;これがDMARCの例

今回はドメインのポリシーpとサブドメインのポリシーspの両方をnone(何もしない最も緩いポリシー)にして宣言している。暫く運用して問題ないようであればnoneからquarantine(迷惑メール扱い・隔離)やreject(受け付けない)に変更する。riは集約レポートの報告間隔(秒)で上の例では(3600=1時間)を指定しているが初期値は86400=1日で普通はこれで良いと思うので指定無しにする。
ruaは集計レポートの宛先(基本はドメインの管理者宛)。rufは認証の失敗レポートの宛先をそれぞれ指定。上の例では失敗レポートだけ指定している。(変更した)
失敗レポートの形式を指定するならrf=afrfとか書く筈だが、afrf以外の値が存在しないのでrfは無指定で良い筈。
ごちゃごちゃ書いたけど、ぶっちゃけvとpとruaだけ指定というので良いかと。

変更したらシリアルの数値を増やすのもお忘れなく。

BINDであればrndc reloadで設定を反映させる。

受信したメールの処理

宣言するだけでもいいんだけどせっかくDMARCに手を付けるなら他所からメールを受信したときに他所様のドメインが宣言しているDMARCの指定に沿ってメールを扱ってやりたいところ。皆が勝手に宣言するだけで受信時に処理しないなら意味がない。「オマエラはオレ様の宣言通りに処理しろ、オレ様はオマエラの宣言は無視して勝手にやる」というところもあるかもだけど。

今回はPostfixで受信したメールのヘッダにDMARCの認証結果を追加する。

# cd /usr/ports/mail/opendmarc
# make install

設定ファイルは/usr/local/etc/mail/opendmarc.conf.sampleを参考に。(FreeBSDのports/pkgの場合)

/usr/local/etc/mail/opendmarc.conf
1
2
3
4
5
6
AutoRestart true
BaseDirectory /var/run/opendmarc
IgnoreHosts /usr/local/etc/mail/opendmarc_ignore.hosts
IgnoreMailFrom example.com
Socket local:/var/run/opendmarc/dmarc.sock
SPFSelfValidate true

SPFはSPFSelfValidate trueで面倒見てくれる。つまり他のSPFのmilter等は停めていい。

/usr/local/etc/mail/opendmarc_ignore.hosts
1
2
3
4
5
localhost
::1
2001:db8::/32
127.0.0.0/8
192.168.0.0/24

ローカルホストとかメールサーバのIPアドレスとか特定のネットワークを無視させる用。

/usr/local/etc/postfix/main.cf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
smtpd_milters =
    unix:/var/run/opendkim/dkim.sock    #DKIM
    unix:/var/run/opendmarc/dmarc.sock
    unix:/var/run/clamav/clmilter.sock  #ClamAV
    unix:/var/run/rmilter/rmilter.sock  #Rmilter

non_smtpd_milters =
    unix:/var/run/opendkim/dkim.sock    #DKIM
    unix:/var/run/opendmarc/dmarc.sock
    unix:/var/run/clamav/clmilter.sock  #ClamAV
    unix:/var/run/rmilter/rmilter.sock  #Rmilter

ClamAVとかRmilterなどは使っている使っていないがある筈。

/etc/rc.conf (追記)
1
2
3
4
opendmarc_enable="YES"
opendmarc_pidfile="/var/run/opendmarc.pid"
opendmarc_socketspec="/var/run/opendmarc/dmarc.sock"
opendmarc_runas="postfix:vmail"

運用開始

# service opendmarc start
# service postfix restart  #こっちは稼働中だろうから再起動
受信したメールのヘッダの中からAuthentication-Results行(複数あるかも)を確認する。
DMARCを宣言していないドメインからのメール
Authentication-Results: mx.example.com; dmarc=none (p=none dis=none) header.from=example.net

DMARCを宣言していて詐称でないメールが届いた。pとdisが表示されている
Authentication-Results: mx.example.com; dmarc=pass (p=none dis=none) header.from=example.org
送信したメールが相手先で宣言したDMARCポリシーが正しく認識されていることを確認する。
今回はDMARCを処理しているGmailで確認。
ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass header.i=@example.com header.s=hoge header.b=xxxxxxxx;
       spf=pass (google.com: domain of foobar@example.com designates 2001:db8::1 as permitted sender) smtp.mailfrom=foobar@example.com;
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=example.com

あなたのドメインがexample.comでメールサーバ(2001:db8::1)が送信したメールアドレスがfoobar@example.comとする。

今回は受信したメールのヘッダにDMARCの結果がAuthentication-Results行として追加されるところまで。受信したメールのDMARCがreject扱いになった場合にそのメールがどう処理されるのかはそういうメールを受けたことがないので未確認。(メールヘッダのAuthentication-Results行にdmarc=failとか書くだけで後はSpamAssassin, Rspamd等配送時の振り分けに任せる?配送に回さず削除?SMTPで550とか554を返して拒否?)
レポート周りは次の記事で。

関連記事:
Up