Postfix + OpenDKIMで送信元ドメイン認証を実装するメモ


個人的メモ。調べてわかったことがあれば書き足す

1. DKIM

1-1. DKIMとは

  • DKIM(Domain Keys Identified Mail)
  • 送信元ドメインを認証するための技術

1-2. 処理の流れ

  1. 送信者が送信メールのヘッダ+本文でハッシュ作成
  2. ハッシュ + 秘密鍵で電子署名作成
  3. 電子署名をDKIM-Signatureヘッダとして添付
  4. メール送信
  5. 受信者が受信メールのヘッダ+本文でハッシュ作成
  6. DKIM-Signatureヘッダの電子署名から公開鍵でハッシュを復号
  7. 受信者が作成したハッシュと比較する

2. 検証環境

  • CentOS6.8
  • Postfix
  • OpenDKIM
    ※ Postfixの設定, BINDとかの設定は事前に適切に行われているものとする ※ example.comは例なので適宜読み替える

3. 手順

3-1. OpenDKIMの導入

標準のレポジトリにはないので、EPELから取ってくる

# yum install -y epel-release
# yum install -y opendkim

3-2. 鍵ペア作成

opendkim-genkeyを利用

opendkim-genkey -D [出力先ディレクトリ] -b [鍵の長さ] -d [ドメイン名] -s [セレクタ名]
(例)
# opendkim-genkey -D /etc/opendkim/keys -b 2048 -d example.com -s 20170309
# ls -l /etc/opendkim/keys/
20170309.private 20170309.txt
# chown -R opendkim:opendkim /etc/opendkim/keys/*

→ セレクタ名.privateとセレクタ名.txtが出来ている

→ xxx.privateが秘密鍵、xxx.txtがDNSのDKIMレコードとなる

→ 秘密鍵は漏洩しないように留意

3-3. KeyTable、SigningTableの更新

KeyTableを更新する

※ DKIMレコードと秘密鍵の関連付け?

# vi /etc/opendkim/KeyTable

以下の書式に従う

DKIMレコード名 ドメイン名:セレクタ名:秘密鍵ファイル
/etc/opendkim/KeyTable
20170309._domainkey.example.com example.com:20170309:/etc/opendkim/keys/20130709.private

SigningTableを更新する

※ どのDKIMレコードに対応する秘密鍵で署名するか決定するテーブル?

# vi /etc/opendkim/SigningTable

以下の書式に従う

対象のメールアカウント DKIMレコード名

なお、ドメインの全てのアカウントを一括指定も可能

/etc/opendkim/SigningTable
# アカウントを指定する書き方
hoge@examle.com 20170309._domainkey.example.com

# ワイルドカードを利用する書き方
*@example.com 20170309._domainkey.example.com

# ワイルドカードを利用しない書き方
@example.com 20170309._domainkey.example.com

3-4. opendkim.confの設定

設定ファイルをバックアップして編集

# \cp -p /etc/opendkim.conf /tmp/
# vi /etc/opendkim.conf

編集結果をdiff取ると、だいたいこんな感じ

# diff /etc/opendkim.conf /tmp/
39c39
< Mode  sv
---
> Mode  v
91c91
< #Selector     default
---
> Selector      default
98c98
< #KeyFile      /etc/opendkim/keys/default.private
---
> KeyFile       /etc/opendkim/keys/default.private
103c103
< KeyTable      /etc/opendkim/KeyTable
---
> # KeyTable    /etc/opendkim/KeyTable
108c108
< SigningTable  refile:/etc/opendkim/SigningTable
---
> # SigningTable        refile:/etc/opendkim/SigningTable
112c112
< ExternalIgnoreList    refile:/etc/opendkim/TrustedHosts
---
> # ExternalIgnoreList  refile:/etc/opendkim/TrustedHosts
115c115
< InternalHosts refile:/etc/opendkim/TrustedHosts
---
> # InternalHosts       refile:/etc/opendkim/TrustedHosts

3-5. OpenDKIM起動

# chkconfig opendkim on
# service opendkim start
# netstat -lntp | grep opendkim
tcp        0      0 127.0.0.1:8891              0.0.0.0:*                   LISTEN      xxxxxx/opendkim

3-6. Postfixの設定を変更

OpenDKIMはmilterとして動作するので、Postfixにmilterの設定を入れる

# vi /etc/postfix/main.cf

末尾に以下を追記

/etc/postfix/main.cf
...
# smtpdプロセスが利用するmilterの定義
smtpd_milters = inet:localhost:8891

# smtpdプロセス以外が利用するmilterの定義
non_smtpd_milters = inet:localhost:8891

# milterがメールを受け取ったときの既定の動作
milter_default_action = accept

3-7. Postfixの設定確認&再起動

# service postfix check
# service postfix reload
# postconf | egrep "(smtpd_milters|milter_default_action)"
milter_default_action = accept
non_smtpd_milters = inet:localhost:8891
smtpd_milters = inet:localhost:8891

3-8. DNSサーバへのTXTレコード登録

出力されたTXTレコードをコピー

# cat /etc/opendkim/keys/20170309.txt

こんな感じのが出力される(鍵ペア作成時の鍵長が長いと結構長い)

20170309._domainkey     IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=xxxxpubkeyxxxxxx..."      "...xxxxxpubkeyxxxxx" )  ; ----- DKIM key 20170309 for example.com

zoneファイルに追記

zoneファイルにTXTレコードを追加する
DKIMレコードとADSPレコードを追加する

BINDの場合の例
/var/named/example.com.zone
20170309._domainkey     IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=xxxxpubkeyxxxxxx..."      "...xxxxxpubkeyxxxxx" )  ; ----- DKIM key 20170309 for example.com  
_adsp._domainkey        IN      TXT     "dkim=unknown" ; DKIMの認証結果に対する取り扱い方針を示す
Route53の場合

Route53 -> Hosted zones -> 該当するDomain Nameクリック -> Create Record Setを選択

DKIMレコードの登録
Name: 20170309._domainkey.example.com
Type: TXT - Text
Alias: No
TTL: 任意
Value: "v=DKIM1; k=rsa; p=xxxxpubkeyxxxxxx..."
Routing Policy: Simple
Save Record Setをクリック

ADSPレコードの登録
Name: _adsp._domainkey.example.com
Type: TXT - Text
Alias: No
TTL: 任意
Value: "dkim=unknown"
Routing Policy: Simple
Save Record Setをクリック

3-9. 名前解決できることを確認

# dig 20170309._domainkey.example.com txt
...
;; ANSWER SECTION:
20170309._domainkey.example.com. 3600 IN TXT    "v=DKIM1\; k=rsa\; " "xxxxxpubkeyxxxxx..." "...xxxxxpubkeyxxxxx"

# dig _adsp._domainkey.example.com txt
...
;; ANSWER SECTION:
_adsp._domainkey.example.com. 3600 IN   TXT     "dkim=unknown"

→ ANSWER SECTIONに想定通りの値が返ってくること。

3-10. メールを送信してみる

自分のGmailアカウント宛にメールを投げてみる

# echo "テストメールですよ" | mail -s "DKIMのテスト" [email protected]

maillogを確認してDKIM-Signatureフィールドが追加されていることを確認する

# tail /var/log/maillog
Mar  9 14:34:44 ns-test opendkim[23066]: 78A3B101059: DKIM-Signature field added (s=20170309, d=example.com)

3-11. 受信結果の確認

Gmailで受信したメールを確認してみる

Authentication-Resultsヘッダが"dkim=pass"となっていることを確認する

Authentication-Results: mx.google.com;
       dkim=pass [email protected];
       ...

以上

3. 参考ページ