Gmail送信者のガイドライン変更の具体的な対応まとめ ~OpenDKIM~

## 1.はじめに
メール送信する機能があるサービスを運用している事業者であれば、
対応に追われているであろう、Gmailメール送信者のガイドラインへの変更。

色々調べた後、SPF,DKIM,DMARCの理解は深めたものの、どのように設定をすればいいかのかパッと分からず、困り果てていたので今回対応した内容についてまとめてみました。

ユースケースに当てはまる方々の役立てば嬉しいです。

尚、当記事では、Gmail送信者のガイドライン変更に関する詳細説明等は参考資料におまかせしております。

### 対象者
- ある程度対応方針について理解がある人
- OpenDkimを利用している方
- 具体的な対応イメージが分からない人

## 2.OpenDkim
Domain Keys Identified Mailの略。
送信メールに電子署名を付与して、なりすましメールでないことを証明する検証方法になります。

OpenDkimでは以下のようなファイルが配置されています。

- KeyTable : レコードと秘密鍵の紐付けを設定
- SigningTable : ドメイン(メールアドレス)とレコードの紐付けを設定
- TrustedHosts : 信頼できるホストを設定 *今回割愛

DMARCをPASSするために修正が必要だったのは、KeyTableとSigningTableの修正でした。

## 3.対応内容
私の場合、SPF,DKIM自体はPASSしている状況でしたが、DMARCはFAILしている状態でした。

ここの理由について理解するのに少し時間がかかってしまったのですが、原因はヘッダFromとエンベロープFromが異なっていることにあり、その理由になるのがOpenDkimの設定でした。

#### <対応前>
以下のように、対応前はメールサーバーのドメインの署名をどのメールに対しても付与している状態でした。
これでは送信元メールのドメインと、メールサーバーのドメイン不一致の場合、DMARCがPASSしません。

```.md:/etc/opendkim/SigningTable

# ワイドルカードで書かれているので、全ての送信元メールアドレスが,mail-server.comの署名となる

*@* selector._domainkey.mail-server.com
```

```.md:/etc/opendkim/KeyTable

# 左辺のDKIMレコードは、右辺のパスの秘密鍵に紐づいてる

selector._domainkey.mail-server.com mail-server.com:selector:/etc/opendkim/keys/server-mail.private
```

#### <試行錯誤>
メールサーバーを経由する送信元メールアドレスが複数存在しうる場合、以下のように設定する必要がありました。

```.md:/etc/opendkim/SigningTable

# メールアドレスと署名が1:1の関係になる

*@from-domain1.com selector._domainkey.from-domain1.com
*@from-domain2.com selector._domainkey.from-domain2.com
*@from-domain3.com selector._domainkey.from-domain3.com
```

```.md:/etc/opendkim/KeyTable

# DKIMレコードと秘密鍵が1:1の関係になる

selector._domainkey.from_domain1.com from_domain1.com:selector:/etc/opendkim/keys/from_domain1.private
selector._domainkey.from-domain2.com from_domain2.com:selector:/etc/opendkim/keys/from_domain2.private
selector._domainkey.from-domain3.com from_domain3.com:selector:/etc/opendkim/keys/from_domain3.private
```

真理に近づきました。

上記は各ドメインに対して一意のレコード、一意の秘密鍵が存在している状態で、おそらく正しい姿です。しかし、ドメインが今後増えていく予定で、ドメイン事に鍵を発行するのも億劫だなと思い、正しいことが正しいとは限らないのマインド(運用コストを少しでも減らす方法)で突き進むことにしました。

メールサーバーを提供している事業者さんだと、DNS管理がユーザーにあって、指定したレコードを追記してもらう必要がありますが、ユーザごとに全て値が異なる為、管理がかなり面倒になってしまいます。

運用コストを減らす為に、CNAMEレコードの採用と、秘密鍵/署名の紐づけ設定を以下のように検討しました。

#### <対応後>

```.md:/etc/opendkim/KeyTable

# 鍵のみ共通とする(server-mail.privateが共通)

selector._domainkey.from-domain1.com from-domain1.com:selector:/etc/opendkim/keys/server-mail.private
selector._domainkey.from-domain2.com from-domain2.com:selector:/etc/opendkim/keys/server-mail.private
selector._domainkey.from-domain3.com from-domain3.com:selector:/etc/opendkim/keys/server-mail.private
```

```.md:/etc/opendkim/SigningTable

# メールアドレスと署名は1:1の関係になる

*@from-domain1.com selector._domainkey.from-domain1.com
*@from-domain2.com selector._domainkey.from-domain2.com
*@from-domain3.com selector._domainkey.from-domain3.com
```

```.md:TXTレコードの設定

# server-mail.privateの対応する公開鍵の設定

selector._domainkey.server-mail.com 3600 IN TXT "k=rsa; t=s; p=xxxxxxxxxxxxxxxxx;"

```

```.md:CNAMEレコードの設定

# 公開鍵が紐づくレコードをCNAMEレコードに追加

selector._domainkey.from-domain1.com 3600 IN CNAME "selector._domainkey.server-mail.com"
selector._domainkey.from-domain2.com 3600 IN CNAME "selector._domainkey.server-mail.com"
selector._domainkey.from-domain3.com 3600 IN CNAME "selector._domainkey.server-mail.com"
```

上記の設定にすることで、運用コスト面はかなり削減できたと思っています。

- ユーザーは一意のレコードを追加することができ、DKIMレコードを貼り付けるよりノンストレス
- 運用者の鍵発行回数も減る (セキュリティ担保する為に、グルーピングして複数個あるとより良い)
- 命名規則さえ決めてしまえば、自動化が見えてくる


## 4.まとめ
- KeyTable：送信元アドレス専用のDKIMレコードと、共通の秘密鍵を紐づける
- SigningTable：送信元アドレスと、送信元アドレス専用のDKIMレコードを紐づける
- DNS設定(TXT)：共通の公開鍵が紐づくレコードを追加
- DNS設定(CNAME) ：送信元アドレス専用のDKIMレコードに、共通の公開鍵が紐づくレコードを追加

レコードで設定している公開鍵と、DKIMで設定した署名/秘密鍵の関係性が妥当性を保てていれば、
CNAMEでなんとかできるんだあとDNSの仕組みに関心しました。

## 5.ぼやき
今回始めてQiita投稿しましたが、うまく文章をまとめきれず結構苦戦しました。
まだまだブラッシュアップできそうなので、書き方については追々修正追加するかもしれません。

人に伝わるように書くって難しい...

## 6.参考
https://note.com/noriyuki_fujita/n/na72eb2688d77
https://www.m3tech.blog/entry/2023/10/24/110000
https://rarutech.hatenablog.com/entry/open_dkim_setting/