自ドメインのDNSとPostfixをSPF/DKIM対応させてみた

#はじめに
[前回](https://qiita.com/Sabuuuuu---nn/items/cb1b51e84b27b2070488)の投稿の続きです。
自ドメインのDNSと前回構築したPostfixをSPFとDKIMに対応させ、さらにセキュアなメール環境を構築していきます。

##1.SPFとDKIM
SPF(Sender Policy Framework)とDKIM(Domainkeys Identified Mail)はいずれも送信ドメイン認証の仕組みであり、IETFによってSPFは[RFC4408](https://www.ietf.org/rfc/rfc4408.txt)、DKIMは[RFC4871](https://www.ietf.org/rfc/rfc4871.txt)および[RFC5672](https://www.ietf.org/rfc/rfc5672.txt)にて仕様が定められています。

SPFはDNSのSPFレコードを利用し送信ドメインを認証します。SPFに対応しているメール受信サーバは、メール受信時に送信元ドメインのDNSサーバのSPFレコードを参照し、送信元のサーバがSPFレコード中で許可されていない場合には送信ドメインの詐称が行われたと判断して、 受信を拒否する等の処理をおこないます。

一方DKIMは電子署名を利用した送信ドメイン認証です。SPFと同様にDNSを利用しますが、DKIMの場合はDNSサーバに送信元ドメインの公開鍵を登録します。送信側メールサーバは自身の秘密鍵で暗号化した電子署名を付加してメールを送信します。メール受信サーバは受信したメールヘッダから特定した送信元ドメインのDNSサーバから公開鍵を取得し、電子署名を検証します。この検証によりなりすまし等を防ぐことが可能となります。

いずれも受信側だけではなく送信側にも対応が求められるものであり、送信側で対応を怠るとたとえ悪意がなくても受信側からメールが拒否される可能性があります。

#2.SPF/DKIM未対応メールサーバからの送信
前回構築したメールサーバはSPF/DKIM未対応です。
その状況で試しにGmailにメールを送信してみましょう。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/318606/c67ae069-bee1-b05e-ec39-ff435f004fe8.png)

Gmailで受信すると・・・迷惑メールとして扱われました。
![02.png](https://qiita-image-store.s3.amazonaws.com/0/318606/4b465c90-4c28-9ff5-0655-785b7a52b045.png)

メッセージの詳細を見てみると・・・・
![03.png](https://qiita-image-store.s3.amazonaws.com/0/318606/4ce9816d-43db-86e6-9c9a-7ddacfa3cef7.png)

なぜかSPFはPASSしてます。何だこれ？
念の為DNSのSPFレコードを[ツール](https://mxtoolbox.com/spf.aspx)を利用して確認します。
![04.png](https://qiita-image-store.s3.amazonaws.com/0/318606/b341f7fb-364b-0b87-101b-66a82e6c4b23.png)
登録されてませんよね・・・Google先生よくわからないですね・・・。

今度はYahooメールに送信してみましょう。
Yahooメールでも迷惑メールとして扱われます。
![05.png](https://qiita-image-store.s3.amazonaws.com/0/318606/15966f7e-1866-4412-4235-29a52bc4737a.png)

メールの詳細を確認するとYahooはちゃんと（ちゃんとというのもおかしな表現だが)SPFはnoneとして扱われています。
![06.png](https://qiita-image-store.s3.amazonaws.com/0/318606/266ee679-2baa-dae9-d8a4-c04ab52ff10f.png)

とりあえずGoogle先生のことはなかったことにして・・・。

#３．SPF対応
まずは自ドメインのDNSに対しSPF対応をおこなっていきましょう。
##3-1.SPFレコードの登録
現在利用しているドメインはDNSに[Route 53](https://aws.amazon.com/jp/route53/)を使用しているのでRoute 53のコンソールからSPFレコードを登録します。

Hosted zonesからドメインを選択してCreate Record Setから登録します。
TypeはSPFが選択できるのですが、[RFC7208](https://www.ietf.org/rfc/rfc7208.txt)のSection 14.1「The SPF DNS Record Type」において「相互接続に問題があるため、SPFレコードの使用は不適切」と定義されているため、<b>TXT</b>レコードを利用します。

今回はhogehoge.co.jpドメインのメールサーバアドレス11.22.33.44のTXTレコードを登録します。

```
hogehoge.co.jp. IN TXT "v=spf1 ip4:11.22.33.44 -all"
```

![01.png](https://qiita-image-store.s3.amazonaws.com/0/318606/f4b0ef1c-d550-58ea-8b74-e5e68d10494b.png)

Route 53では
Name:空白
Type:TXT - Text
Value:"v=spf1 ip4:11.22.33.44 -all"
として登録します。

なおメールサーバが複数台ある場合は
"v=spf1 ip4:11.22.33.44 ip4:22.33.44.55 ip4:33.44.55.66-all"
と複数台のアドレスを続けて記載していきます。

##3-2.SPFレコードの確認

先程も使用した[ツール](https://mxtoolbox.com/spf.aspx)で改めてチェックしてみましょう。
![02.png](https://qiita-image-store.s3.amazonaws.com/0/318606/b690a3cf-ed50-f0b5-ae87-ce07a061c174.png)

ちゃんと参照ができました。

#4.DKIM対応
引き続きDNSとPostfixに対しDKIM対応を行っていきます。

##4-1.OpenDKIMインストール
OpenDKIMを使用し秘密鍵、公開鍵の生成をしていきます。
Amazon Linux2にELバージョン7のEPELリポジトリを追加しOpenDKIMをインストールします。

```Bash
$ sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
$ sudo yum install opendkim
```
##4-2.公開鍵と秘密鍵の作成
DNSに登録する公開鍵と署名に使用する秘密鍵の作成をおこないます。
まずは任意の場所に鍵を保存するディレクトリを作成します。

```Bash
$ sudo mkdir /etc/opendkim/keys/hogehoge.co.jp
```

作成したディレクトリ内にopendkim-genkeyコマンドで鍵を作成します。

```Bash
$ sudo opendkim-genkey -D /etc/opendkim/keys/hogehoge.co.jp/ -d hogehoge.co.jp -s default
```
-D 鍵の作成されるディレクトリ
-d ドメイン名
-s セレクタ名（任意の名称）

ディレクトリを参照すると公開鍵と秘密鍵が作成されています。

```Bash
$ sudo ls /etc/opendkim/keys/hogehoge.co.jp/
default.private  default.txt
```
[セレクタ名].private・・・秘密鍵
[セレクタ名].txt・・・公開鍵

鍵のオーナーをopendkimに変更します。

```Bash
$ sudo chown -R opendkim:opendkim /etc/opendkim/keys
$ sudo ls -l /etc/opendkim/keys/hogehoge.co.jp/
合計 8
-rw------- 1 opendkim opendkim 887 12月  4 13:42 default.private
-rw------- 1 opendkim opendkim 318 12月  4 13:42 default.txt
```

##4-3.DKIMレコードの登録
DNSにDKIMレコードを登録します。
DKIMレコードの書式は下記の通りです。

```Bash
[セレクタ名]._domainkey.[ドメイン名].  IN TXT "v=DKIM1; k=rsa; p=公開鍵"
```
公開鍵は生成された鍵ファイルの中に記載されています。

```Bash
$ sudo cat /etc/opendkim/keys/hogehoge.co.jp/default.txt
default._domainkey	IN	TXT	( "v=DKIM1; k=rsa;"
	  "p=************************************************************************************************************************************************************************************************************************" )  ; ----- DKIM key default for hogehoge.co.jp
```

Route53でDKIMレコードを追加していきます。
![03.png](https://qiita-image-store.s3.amazonaws.com/0/318606/f85f9a02-ae26-f3e7-1799-dd766de19df5.png)
Name:[セレクタ名]._domainkey
Type:TXT - Text
Value:"v=DKIM1; k=rsa; p=公開鍵"

##4-4.ADSPレコードの登録
ついでにDKIMの機能の一つであるADSP(Author Domain Signing Practice)レコードも登録しておきます。
ADSPはメール受信時にDKIM署名が有効ではない（認証結果のスコアが「dkim=pass」ではない）メールの取り扱いを、メールの送信者側が設定できる機能で、[RFC5617](https://www.ietf.org/rfc/rfc5617.txt)で標準化されています。

ADSPレコードの書式は下記の通りです。

```Bash
_adsp._domainkey.[ドメイン名].  IN TXT "dkim=レコード値"
```
ADSPレコードの値は以下のいずれかを指定できますが、今回はdkim=unknownとしました。

| ADSPレコード値 | 意味 |
|:-----------|:-----------|
|dkim=unknown|DKIM署名していないメールも送信する。|
|dkim=all|送信するメールはすべてDKIM署名をおこなっっている。|
|dkim=discardable|DKIM署名がされていなかったり不正な署名のメールはすべて削除してよい|

同様にRoute 53で登録します。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/318606/4d23748c-cc6e-7548-1ada-2ed4dd69ff1f.png)
Name:_adsp._domainkey
Type:TXT - Text
Value:"dkim=unknown"

##4-5.DKIMレコードの確認
こちらの[ツール](https://dmarcian.com/dkim-inspector/)を利用して確認してみましょう。いろいろなツールが公開されているので便利ですよね。まぁむやみによくわからないサイト使うと変なもの仕込まれたりすることもあるのですがw
![02.png](https://qiita-image-store.s3.amazonaws.com/0/318606/79ae9407-23ee-41ad-4367-a76fb6ac002c.png)

ちゃんと参照ができました。

#5.OpenDKIMとPostfixの連携
引き続きOpenDKIMの設定をおこないPostfixでDKIM署名を利用出来るようにしていきます。

##5-1.opendkim.conf
OpenDKIMの設定ファイルをviで開き設定をおこなっていきます。

```Bash
$ sudo cp /etc/opendkim.conf /etc/opendkim.conf.back
$ sudo vi /etc/opendkim.conf
```

```Bash:opendkim.conf
#モードの設定 s:送信時に署名する v:受信時に確認する
Mode    sv

#KeyfileではなくKeyTableを利用する。
#KeyFile        /etc/opendkim/keys/default.private   ←コメントアウト
KeyTable        refile:/etc/opendkim/KeyTable   ←コメントインして修正

#署名するドメインの指定を可能とする。
SigningTable    refile:/etc/opendkim/SigningTable   ←コメントイン

#外部ホストの特定
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts   ←コメントイン

#内部ホストの特定
InternalHosts   refile:/etc/opendkim/TrustedHosts   ←コメントイン
```
##5-2.秘密鍵の登録
KeyTableに署名に使用する秘密鍵を登録します。

```Bash
$ sudo vi /etc/opendkim/KeyTable
```

```Bash:KeyTable
default._domainkey.hogehoge.co.jp hogehoge.co.jp:default:/etc/opendkim/keys/hogehoge.co.jp/default.private
```

##5-3.ドメイン指定
署名をおこなうドメインを指定します。

```Bash
$ sudo vi /etc/opendkim/SigningTable
```

```Bash:SigningTable
*@hogehoge.co.jp default._domainkey.hogehoge.co.jp
```

##5-4.ホストの指定
DKIM署名を使用するPostfixサーバのアドレスを設定します。今回はOpenDKIMとPostfixは同一のサーバにインストールされているので初期値で登録されているループバックアドレスのままで問題ありません。OpenDKIMとPostfixが別環境にある場合は追加でアドレスの登録をおこなってください。

```Bash
$ sudo vi /etc/opendkim/TrustedHosts
```

```Bash:TrustedHosts
# The localhost IP (127.0.0.1) should always be the first entry in this file.
127.0.0.1
::1
#host.example.com
#192.168.1.0/24
```

##5-5.OpenDKIMの起動
OpenDKIMの起動と自動起動の設定をおこないます。

```Bash
$ sudo service opendkim start
$ sudo chkconfig opendkim on
```

##5-6.main.cf
PostfixでDKIMを利用する設定をおこないます。

```Bash
$ sudo vi /etc/postfix/main.cf
```

main.cfの最後にDKIMを利用する記述を追加します。

```Bash:main.cf
#DKIM利用
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:localhost:8891
milter_default_action = accept
```
保存したらPostfixを再起動しておきましょう。

```Bash
$ sudo service postfix restart
```

#6.確認
正しく設定されたか確認してみます。
設定前と同様にYahooメールにメールを送信してみます。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/318606/f12aaffc-6eb7-bb99-9903-bad523adac2a.png)

![03.png](https://qiita-image-store.s3.amazonaws.com/0/318606/46631dd8-2151-5b5d-c5ff-1e4c9c0ac5f8.png)

SPFの設定とDKIM署名がおこなわれているのが確認できました。

#まとめ
自社のメールを運用するにあたりSPFやDKIMの導入は現在では必須だと思われます。実際に総務省でも導入を推進しており、定期的にJPドメインにおける普及状況を[発表](http://www.soumu.go.jp/menu_news/s-news/01kiban18_01000035.html)しています。

サーバ管理者であればそれほど難しい作業でもないのでメールサーバの運用管理者は必ず設定をおこなっていくようにしましょう。