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

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

## 1. DKIM
### 1-1. DKIMとは
- DKIM(**D**omain **K**eys **I**dentified **M**ail)
- 送信元ドメインを認証するための技術  

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

## 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レコード名 ドメイン名:セレクタ名:秘密鍵ファイル
```
```conf:/etc/opendkim/KeyTable
20170309._domainkey.example.com example.com:20170309:/etc/opendkim/keys/20130709.private
```

#### SigningTableを更新する  
※ どのDKIMレコードに対応する秘密鍵で署名するか決定するテーブル？  

```
# vi /etc/opendkim/SigningTable
```

以下の書式に従う  

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

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

```conf:/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
```

末尾に以下を追記

```conf:/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のテスト" hoge@gmail.com
``` 

#### 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 header.i=@example.com;
       ...
```

以上

## 3. 参考ページ  
- DKIMの仕組み
[一般財団法人インターネット協会 - 技術解説 DKIM (Domainkeys Identified Mail)](http://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/dkim/)
[レンタルサーバー・自宅サーバー設定・構築のヒント - DomainKeys Identified Mail (DKIM) の仕組み](http://server-setting.info/blog/domainkeys-identified-mail.html)

- Postfix + DKIMの実装手順
[あぱーブログ - Postfix DKIM 認証 設定メモ（CentOS6.5＋OpenDKIM）](https://blog.apar.jp/linux/856/)