PostfixにOpenDKIMを導入してDKIM・DMARCを設定する(AlmaLinux 9)

この記事について

環境AlmaLinux 9 + Postfix(旧CentOS 6.8時代のコマンドも併記)
目的OpenDKIMを導入してDKIM署名 → DNS設定 → DMARC設定まで行う
結果サーバーから送信したメールも、webフォーム経由のメールも DKIM: PASS になった

つまずきポイント要約

途中でつまずいた点は以下の3つ。詳細は各セクションに記載。

  • AlmaLinux 9 で opendkim のインストールが依存関係エラーで失敗 → crb リポジトリを有効化して解決
  • opendkim-testkey が秘密鍵を見つけられない → KeyFile ではなく KeyTable 方式に変更して解決
  • webフォーム経由のメールだけ DKIM: FAIL(body hash did not verify)→ PHP ファイルの改行コード(CRLF)が原因

参考サイト

CentOSのPostfixで迷惑メール判定されないようDKIMを設定する
構築したメールサーバーから送信したメールが迷惑メールとして識別されたことはありませんか?このような場合は、送信したメールが経由するメールサーバーのなりすましメール対策に引っかかっている場合が殆どです。

DKIMのインストール

インストールできるかの確認

yum info opendkim

インストール

sudo yum install opendkim

つまずき①:AlmaLinux 9 でインストールに失敗する

事象:almalinux9 では一度失敗した。エラー内容は以下。

Error:
 Problem: conflicting requests
  - nothing provides libmilter.so.1.0()(64bit) needed by opendkim-2.11.0-0.36.el9.x86_64 from epel
  - nothing provides libmemcached.so.11()(64bit) needed by opendkim-2.11.0-0.36.el9.x86_64 from epel
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)

原因:epel の opendkim が要求する依存パッケージ(libmilter, libmemcached)が、デフォルトで有効なリポジトリに存在しない。これらは crb(旧 PowerTools)リポジトリに入っている。

対処:crb リポジトリを有効化する。

sudo dnf config-manager --set-enabled crb

crb リポジトリが有効になったことを確認

sudo dnf repolist all

再度インストール

sudo yum install opendkim

インストールできているかの確認

yum list installed | grep opendkim

インストールによって opendkim ユーザが作成されているはず

$ id opendkim
uid=498(opendkim) gid=499(opendkim) 所属グループ=499(opendkim),12(mail)

インストールができたら鍵の生成を行う

鍵の生成

鍵を保存するディレクトリを作成

mkdir /etc/opendkim/keys/mydomain.com

opendkim-genkey が使えるかの確認

opendkim-genkey --help

なければ opendkim-tools をインストール

sudo yum install opendkim-tools
# -s はセレクタ(鍵の名前)
$ sudo opendkim-genkey -D /etc/opendkim/keys/mydomain.com/ -d mydomain.com -s default

default.private と default.txt の二つのファイルができていることを確認

$ sudo ls keys/mydomain.com
default.private default.txt

default.private(秘密鍵)default.txt(公開鍵)

opendkim からファイルにアクセスできるよう、所有者を変更

$ sudo chown -R opendkim:opendkim /etc/opendkim/keys/mydomain.com/

注意:秘密鍵の権限は緩すぎても opendkim がエラーを出す。600 にしておくのが安全。不用意に変更しない。

DNSの設定

DNSにTXTレコードを追加する。登録する内容は、さきほど生成された default.txt に書いてある。

$ sudo cat /etc/opendkim/keys/mydomain.com/default.txt
[sudo] password for user1:
default._domainkey      IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" )  ; ----- DKIM key default for mydomain.com

v=DKIM1は、DKIMのバージョン。k=rsaは、鍵のアルゴリズムがRSAであることを示す。p=xxxxxxは、公開鍵の値。

なお、本記事冒頭の参考ブログに書いてあったADSPレコードの登録は、すでに廃止された仕様なので現在は必要ない(下記IIJの記事を参照)。

DKIM ADSP は廃止されています (HISTORIC です) | IIJ Engineers Blog
結論 (HISTORIC) (※1) 新しくドメイン名を登録された方へ ...

DNSに反映されたかの確認

dig txt default._domainkey.mydomain.com

動作テスト

$ opendkim-testkey -d mydomain.com -s default -vvv #-vvvは詳細表示

つまずき②:opendkim-testkey が秘密鍵を見つけられない

事象:動作テストで以下のエラーが出る。

opendkim-testkey: /etc/opendkim/keys/default.private: stat(): No such file or directory

原因:opendkim-testkeyはデフォルトで/etc/opendkim/keys/直下を参照する。今回は鍵をドメイン名のサブディレクトリに置いたため、パスが一致していない。

対処:OpenDKIMの設定ファイル/etc/opendkim.confで鍵ファイルの場所を正しく指定する。編集前に念のため opendkim.conf をコピーしておく。

秘密鍵のパスの指定方法は KeyFile と KeyTable の2通りあり、いずれかを使う。KeyFile は単一ドメイン向け、KeyTable は1つのサーバーで複数のドメインやセレクタを運用する場合向け。今回は後々の拡張も考えて KeyTable を選択。以下のように書き換える。

KeyFile /etc/opendkim/keys/default.private

# KeyTable      /etc/opendkim/KeyTable

↓↓↓ KeyFile を無効にして KeyTable を有効化

# KeyFile /etc/opendkim/keys/default.private

KeyTable      /etc/opendkim/KeyTable

KeyTable に「セレクタ ドメイン:セレクタ名:秘密鍵のパス」を記述

#一行で
default._domainkey.mydomain.com mydomain.com:default:/etc/opendkim/keys/mydomain.com/default.private

再度テストして、エラーが出なければOK

$ opendkim-testkey -d mydomain.com -s default -vvv #-vvvがないとエラー以外何も出ない

KeyTable を使用する場合 SigningTable も必要なので有効にする

# SigningTable refile:/etc/opendkim/SigningTable
↓↓↓
SigningTable refile:/etc/opendkim/SigningTable

SigningTableの記述例。「このアドレスから送るメールは、この鍵で署名する」という対応表。

*@[ドメイン名] ._domainkey.[ドメイン名]
# 例 *はワイルドカードで、すべてのアドレスを意味する
*@mydomain.com default._domainkey.mydomain.com

その他 opendkim.conf の変更箇所。Mode sv は署名(s)と検証(v)の両方を行う設定。SoftwareHeader はバージョン情報をヘッダに出す設定なので、情報漏えい防止のため無効化。

Mode v
↓
Mode sv


SoftwareHeader  yes
↓
SoftwareHeader  no


# ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
↓
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts


# InternalHosts refile:/etc/opendkim/TrustedHosts
↓
InternalHosts refile:/etc/opendkim/TrustedHosts

# OpenDKIMとPostfixの通信方法
# 今回はTCPソケット(inet:8891)を利用するので切り替える
#Socket  inet:8891@localhost
Socket local:/run/opendkim/opendkim.sock
↓
Socket  inet:8891@localhost
#Socket local:/run/opendkim/opendkim.sock

opendkim が起動しているか

service opendkim status

自動起動の確認

chkconfig --list opendkim #centOS6.8
もしくは
sudo systemctl is-enabled opendkim #almalinux9

サーバー再起動時の自動起動

sudo chkconfig opendkim on #centOS6.8
もしくは
sudo systemctl enable opendkim #almalinux9

postfixとDKIMを連携させる

postfix 側にも、メールを milter(OpenDKIM)に渡すための設定が必要。main.cf の最下段に記述する。ポート番号は opendkim.conf の Socket で指定した 8891 に合わせる。

# DKIMと連携させるための記述
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept

設定のエラーチェック

postfix check

再起動して反映

sudo systemctl restart postfix

送信テスト

$ echo "テストメールです" | sendmail -t -f renraku@example.com test@gmail.com

届いたgmailのソースを見て DKIM:’PASS’ となっていれば成功

つまずき③:webフォーム経由のメールだけ DKIM:’FAIL’ になる

事象:コマンドからの送信テストは PASS するのに、運営サイトのwebフォームから送ったメールは DKIM:’FAIL’ となった。メールのソースを見ると body hash did not verify となっている。

原因:署名時と検証時で本文のハッシュ値が一致していない。調べると、改行コードが「\n」でなく「\r\n」になっているとこのエラーになるらしい。フォームのPHPファイルを確認すると、ファイル自体の改行コードがCRLFになっており、メール本文の文字列に生の改行(\nや\r\nのエスケープではなく、ソース上の物理的な改行)が入っていた。つまり本文にCRLFがそのまま混入していた。

対処:本文中のこの改行を削除したら DKIM:’PASS’ となった。

エラー解決参考

DKIMで「body hash did not verify」というエラーが出る。
DKIMで「body hash did not verify」というエラーが出る。 Centos6.6、pos

さくらのメールボックスのwebメールで送信するときのDKIM認証

ここまでの設定は、運営しているwebサーバーから送信したメールのDKIM認証のやり方。さくらのメールボックスのwebメールから送信する場合は、さくらのSMTPサーバーを経由するため、このサーバーでの署名は行われず、DKIM認証されない。経路上で実際にメールを送信するSMTPサーバーが署名を行う必要があるので、さくら側での設定が別途必要。

やり方のページ

DKIM署名、ARC署名、DMARCを設定したい | さくらのサポート情報
このマニュアルでは、DKIM署名、ARC署名およびDMARCの設定についてご案内しています。DKIM/ARC/DMARCとはDKIM送信する電子メールに電子署名し、受信者がDNSを経由して署名を検証することで、間違いなく送信されたドメインから送られてきていることを確認し、送信ドメ

上記URLを参考に、webサーバー上にある秘密鍵をさくらのメールボックスのSMTPサーバーにアップロードする。セレクタ名も同じにして設定を完了すれば、webメールやiphoneからの送信もDKIM認証が使えるようになる。

DMARCの設定

SPFとDKIMの設定が終わったらDMARCも設定する。DNSにTXTレコードを1つ追加するだけ。

ホスト名

_dmarc.<ドメイン名>

txtレコード。まずは p=none(監視のみ)で運用開始し、レポートを見て問題なければ quarantine や reject に引き上げる方針。

v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com

openDKIMをmonitの監視対象にする

opendkim が落ちるとメールが署名されなくなるので、monit で死活監視して自動復旧させる。monit の設定に以下を追加。

check process opendkim with pidfile /var/run/opendkim/opendkim.pid
  start program = "/usr/sbin/service opendkim start"
  stop program  = "/usr/sbin/service opendkim stop"
  if 5 restarts within 5 cycles then timeout

monitを再起動

$ sudo /sbin/service monit restart

確認

sudo monit summary

動作確認として、openDKIMを手動で停止し、monit が自動で再起動させるか見てみる。

$ sudo /sbin/service opendkim stop
タイトルとURLをコピーしました