Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」


投稿日:2019年11月23日
  • 2
  • 0


Gmailにセキュアなメールサーバと認識されるために必要な設定

以前の投稿で紹介しましたが、当ブログも利用しているGMO系列のWebサーバでGmailへのメール送信ができなくなるという障害が発生しました。(現在は復旧済み)

今回の原因はGMOのサーバ利用者がスパムメールを大量に送信したため、GMOに割り振られたIPが範囲ごとブロックされるというものでした。

GMO VPSには障害情報を通知する仕組みがありません。そのため一利用者の私としては原因探しに奔走することになりました。
その奔走の中で「Gmail でメールがブロックされる理由」というページを発見しました。

今回の件とは関係がなかったものの、メールサーバのセキュリティを向上させるには大切な内容だったので、皆様と共有したいと思います。

目次


GoogleのPostmaster Toolsを利用する

上で紹介した「Gmail でメールがブロックされる理由」というページでも触れられていますが、Gmailには「Postmaster Tools」というツールが存在します。

Postmaster Toolsとは大量のメールを送受信するユーザーが利用するメール版のAnalyticsのようなサービスです。
具体的には以下の項目を調べることができます。

  • ●迷惑メール率
  • ●IPレピュテーション
  • ●ドメインレピュテーション
  • ●フィードバックループ
  • ●認証
  • ●暗号化
  • ●配信エラー

これらの指標を利用して迷惑メールに登録された原因や問題点を洗い出すのに利用します。
設定するにはまずはPostmaster Toolsにアクセスします。
するとスタートガイドが始まるので手順通りに進めます。

メールの認証に使用するドメインの入力

まずは「メールの認証に使用するドメイン」を入力します。いわゆるGmailへ接続するメールサーバのドメイン(例えばexample.com)です。入力したら「次へ」をクリック。

DNSへのTXTレコードの追加

続いてドメインの確認の為のTXTレコードをコピーして、DNSへ追加します。

BINDを利用したDNSの設定については詳しくは以前の投稿を見てもらうとして、私の場合は以下のように設定しました。
example.comは環境に合わせて適宜読み替えてください。

# vi /var/named/example.com.hosts
$ttl 38400
example.com.	IN	SOA	ns.example.com.	info.example.com. (
		1347519085			; シリアル番号
		10800				; リフレッシュ間隔
		3600				; リトライ間隔
		604800				; ゾーンの有効期
		38400 )				; ネガティブキャッシュ有効期間
example.com.	IN	NS	ns.example.com.		; このゾーンのプライマリマスタ
example.com.	IN	NS	ns3.maihama-net.com.	; マイハマnetのセカンダリマスタ
example.com.	IN	MX	10 mail.example.com.	; メール用
example.com.	IN	TXT	"google-site-verification=E16-8F4wgoV1575-b6CU1556515693uHsTIoU2fdbmy6M"	; メールの認証
(省略)

最終行のTXTレコードが認証用のコードです。ダブルコーテーションで囲むのを忘れないようにしてください。
設定ができたらシリアル番号を一つ進めて念のためにBINDを再起動します。

# /etc/init.d/named restart

あとは内容が伝播するのを待ちます。(伝播って言うな問題はry)
すぐに確認ボタンをクリックしても、以下のような表示になると思います。

確認が取れると、以下のように表示されます。

これで一応Postmaster Toolsの下準備が完了しました。
なぜ下準備かと言うと、これから下記で解説するSPFやDKIMといった認証技術を導入しないと正確にカウントされないためです。
また、Postmaster Toolsは大量にメールを送受信するサーバで有効なサービスです。月に数十通程度では統計は表示されません。そのため、一般のメールサーバではドメインの正当性と、正しい認証技術を利用していることをGoogleへ通知するのが目的です。いわゆるGoogleへの点数稼ぎです。


SPF(Sender Policy Framework)を利用する

Sender Policy Framework(センダー・ポリシー・フレームワーク)とはメールを送信するIPを限定する認証方法です。
DNSのTXTレコードへメール送信者のIPを記述することで設定します。受信側はDNSへ記述されたIPと実際にメールを送信してきた相手のIPを照合することで、なりすましを防ぎます。

更に詳しい仕組みを知りたい方は「なりすましメール撲滅に向けたSPF(Sender Policy Framework)導入の手引き:IPA 独立行政法人 情報処理推進機構」をご覧ください。

考えてみればSPF認証のないメールは手紙の差出人を無条件で本人と認定しているようなものです。物騒な世の中で、これはいただけません。

余談ですがSPFを提唱したSender Policy Frameworkの公式Webページは資金不足で閉鎖しています。なんとも世知辛い話ですね。

では設定を行います。
仕組みが簡単なら、設定も簡単です。先程GoogleのPostmaster Toolsを設定したときと同じようにDNSへSPF用のTXTレコードを追加するだけです。
私はわかりやすいようにPostmaster Tools用のコードの次の行に追加しました。

oxynotes.com.	IN	TXT	"google-site-verification=E16-8F4wgoVuvLh-b6CUks6515061auHsTIoU2fdbmy6M"	; メールの認証
oxynotes.com.	IN	TXT	"v=spf1 +ip4:153.122.40.105 -all"	; SPFレコード

特に解説する要素もないですが、v=spf1SPFVersion 1という意味のようです。
+ip4:153.122.40.105」の部分にメールサーバのIPを記述します。この例ではIPが一つだけですが、複数のIPがある場合はスペース区切りで「+ip4:153.122.40.105 +ip4:153.122.40.106」といった具合に追記します。

最後の「-all」は全てのメールで指定したIPを利用するということのようです。
通常であれば定型文のようにallを追記しますが、リダイレクトする場合などは記述しないようです。
例えばhoge.example.comのメールはexample.comで送受信を行うといった場合は以下のように記述します。

hoge.example.com. TXT "v=spf1 redirect=_spf.example.com"
_spf.example.com. TXT "v=spf1 mx:example.com -all"

その他にもたくさんの応用例があるので、複雑なメールサーバを運用している方は公式のドキュメントをご覧ください。

正しく設定できたかどうかはSUPERTOOL!というサイトで確認することができます。
ドメインを入力して、プルダウンメニューから「SPF Record Lookup」を選択して実行してください。
正しく設定できていれば以下のような表示になります。(この画像の場合は複数のIPを指定した例です)


DKIM(Domainkeys Identified Mail)を利用する

続いてDomainkeys Identified Mail(ドメインキー・アイデンティファイド・メール)という認証技術を導入します。
簡単に言えば電子署名を利用して送信ドメインを認証する技術です。

具体的にはメールの送信元が電子署名で暗号化を行い、DNSへ公開鍵の情報を公開します。受信側はDNSに記述された公開鍵情報を元に検証し、暗号化されたメールの復号化を行います。つまりメール版の公開鍵認証です。

仕組みがわかったところで、早速設定してみます。

DKIMに利用する秘密鍵と公開鍵を作成するにはOpenDKIMを利用します。
EPELリポジトリを利用してインストールしてください。

# yum install opendkim --enablerepo=epel

(省略)

Dependencies Resolved

================================================================================
 Package                Arch          Version                 Repository   Size
================================================================================
Installing:
 opendkim               x86_64        2.11.0-0.1.el6          epel        215 k
Installing for dependencies:
 libbsd                 x86_64        0.8.3-2.el6             epel         83 k
 libopendkim            x86_64        2.11.0-0.1.el6          epel         71 k
 opendbx                x86_64        1.4.6-6.el6             epel         45 k
 sendmail-milter        x86_64        8.14.4-9.el6_8.1        base         57 k

Transaction Summary
================================================================================
Install       5 Package(s)

Total download size: 472 k
Installed size: 1.1 M
Is this ok [y/N]: y ←YESの「y」と入力してエンター

OpenDKIMの使い方は「OpenDKIM – ArchWiki」で詳しく解説されています。

今回はマルチドメイン(同一サーバで複数のサイトを運営)の場合を想定して解説を進めます。
まずは鍵を保存するディレクトリを作成します。マルチドメインということで「/etc/opendkim/keys/」の中にドメイン名のサブディレクトリを作成し、その中にそれぞれのサイト用の鍵を生成します。

# mkdir /etc/opendkim/keys/example.com

続いてopendkim-genkeyで鍵を作成します。

# opendkim-genkey --directory=/etc/opendkim/keys/example.com --domain=example.com --bits=2048 --selector=example

それぞれのオプションの意味は以下のようになります。

--directory 鍵を作成するディレクトリの指定
--domain 作成するドメインの指定
--bits=2048 鍵長
--selector 鍵の参照に利用するセレクタ(後にDNSに記述する)

他のドメインがある場合は、それぞれディレクトリを作成し、対応する鍵を作成してください。

鍵ができたらディレクトリの所有権を変更しておきます。

# chown -R opendkim:opendkim /etc/opendkim/*

DNSへADSPレコードの追加

DNSへ公開鍵の設定をする前にADSPレコードを追加します。
ADSPレコードとは公開鍵認証をした結果、どのようにメールを扱うかを指定するものです。

# vi /var/named/example.com.hosts
_adsp._domainkey.example.com.	IN	TXT	"dkim=unknown"

私の場合は上で設定したSPFレコードの直下に追記しました。
追記が完了したらシリアル番号を進めて保存します。

ADSPレコード値の意味は以下のとおりです。

dkim=unknown DKIM署名していないメールも送信している
dkim=all 送信するメールはすべてDKIM署名している
dkim=discardable DKIM署名されていないメールまたは不正な内容のDKIM署名がされているメールが届いた場合は、すべて破棄してよい。

普通に考えれば「all」が一番セキュリティ上安全ですが、配送経路で再署名された際などに厳格すぎると弾かれる可能性があります。今回の目的はセキュリティに配慮してメールを正しく届けることなので「unknown」にします。

ドメインキーが正しく設定できているかどうかは以下のコマンドで確認できます。

$ host -t txt _adsp._domainkey.example.com
_adsp._domainkey.example.com descriptive text "dkim=unknown"

上記のように出力されれば正しく設定できています。

DNSへ公開鍵の追加

それではOpenDKIMで作成した公開鍵をDNSへ記述します。
とりあえず作成された公開鍵を開きます。

# vi /etc/opendkim/keys/example.com/example.txt

すると以下のような形式になっています。

example._domainkey     IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmySj0PzDNa4TpTOCfcmXk67QfjqO+7e8Z1bd9MgZeWUwdLPBICQbdzwxg921QmFx9I3eCmY1T7iYZHDU/q6F4shSwJkowHbQowVtgXyjlIHW7YUxqcVFaMavcMjilOgItRuyuWVNa/c4KuzLaoKWe0+sRJYwzdq2hnz0bAnlbzF70odk1scu561513O44ESigr0Ddzp1ss7rHu5"
          "yPqDkXD4UFTz/CcSqjK50le/c+/zkoDiiy3CkYfKODql556527Zo/xvoKr26E+XmpMoExypNq07rVL6/87qrLMgCd82IAszadHo+6iHSnysKefRg/TATbQV8/hMbG5064wtrwQIDAQAB" )  ; ----- DKIM key example for example.com

まずTXTレコード全体が()で囲まれています。これはDNSの書式で、()内を一行とみなしています。
なぜ()で囲んで改行されているかというと、DNSのTXTレコードは一行の文字数が256文字で制限されているためです。
つまり、長い鍵長の場合はTXTレコードへコピペしやすいように分割してくれているというわけです。

ただし注意点として、INやTXT等はあくまでサンプルで、区切り文字などは既存の書式に合わせる必要があります。

私の場合はspfレコード直下に以下のように追記しました。

example._domainkey.example.com.     IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmySj0PzDNa4TpTOCfcmXk67QfjqO+7e8Z1bd9MgZeWUwdLPBICQbdzwxg921QmFx9I3eCmY1T7iYZHDU/q6F4shSwJkowHbQowVtgXyjlIHW7YUxqcVFaMavcMjilOgItRuyuWVNa/c4KuzLaoKWe0+sRJYwzdq2hnz0bAnlbzF70odk1scuSWmlcO44ESigr0Ddzp1ss7rHu5"
          "yPqDkXD4UFTz/CcSqjK50le/c+/zkoDiiy3CkYfKODqli0j527Zo/xvoKr26E+XmpMoExypNq07rVL6/87qrLMgCd82IAszadHo+6iHSnysKefRg/TATbQV8/hMbG7E9xlfwtrwQIDAQAB" )  ; ----- DKIM key example for example.com

シリアル番号を進めて保存します。
必要なら他のドメイン分も同じように追加してください。

設定が完了したら念の為BINDを再起動します。

# /etc/init.d/named restart

では正しく設定できているか調べます。

$ dig txt example._domainkey.example.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.el6_9.2 <<>> txt example._domainkey.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13876
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;example._domainkey.example.com. IN   TXT

;; ANSWER SECTION:
oxynotes._domainkey.example.com. 38400 IN TXT  "v=DKIM1\; k=rsa\; " "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmySj0PzDNa4TpTOCfcmXk67QfjqO+7e8Z680465654BICQbdzwxg921QmFx9I3eCmY1T7iYZHDU/q6F4shSwJkowHbQowVtgXyjlIHW7YUxqcVFaMavcMjilOgItRuyuWVNa/c4KuzLaoKWe0+sRJYwzdq2hnz0bAnlbzF70odk150646532ESigr0Ddzp1ss7rHu5" "yPqDkXD4UFTz/CcSqjK50le/c+/zkoDiiy3CkYfKODqli0j527Zo/xvoKr26E+XmpMoExypNq07rVL6/87qrLMgCd451656565+6iHSnysKefRg/TATbQV8/hMbG7E9xlfwtrwQIDAQAB"

;; Query time: 106 msec
;; SERVER: 180.222.191.15#53(180.222.191.15)
;; WHEN: Sun May  5 20:46:11 2019
;; MSG SIZE  rcvd: 475

このように表示されれば、正しく設定できています。

SPFの時に利用したSUPERTOOL!でも調べることができます。
今度は「DKIM Lookup」を選んで実行してください。(実際に送信するメールが暗号化されるのは下記の設定を完了してからです)

それぞれ「v, k, p」の値が正しく連動していることを確認してください。

OpenDKIMのKeyTableを更新

OpenDKIMのKeyTableを更新します。
KeyTableとは鍵とドメインを関連付ける設定ファイルです。

KeyTableは以下の書式で行います。

DKIMレコード名 ドメイン名:セレクタ名:秘密鍵ファイル

では早速編集をします。

# vi /etc/opendkim/KeyTable
# OPENDKIM KEY TABLE
# To use this file, uncomment the #KeyTable option in /etc/opendkim.conf,
# then uncomment the following line and replace example.com with your domain
# name, then restart OpenDKIM. Additional keys may be added on separate lines.

#default._domainkey.example.com example.com:default:/etc/opendkim/keys/default.private

example._domainkey.example.com example.com:example:/etc/opendkim/keys/example.com/example.private

複数のドメインがある場合は改行して複数記述してください。
コメントにありますが「/etc/opendkim.conf」の「KeyTable」を有効にする必要があります。

/etc/opendkim.conf」の以下の項目が対応しています。(設定は後ほど行います)

KeyTable refile:/etc/opendkim/KeyTable

OpenDKIMのSigningTable更新

つづいてSigningTableを更新します。SigningTableとは許可するユーザーをドメインごとに関連付けるファイルです。

書式は以下の通り。

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

ユーザーを追加するごとにユーザー名を指定するのは面倒という場合はワイルドカードが使用可能です。
ただし、ワイルドカードで全てのユーザーを許可してしまうと、SigningTableの意味が無くなってしまいます。ユーザーが決まっているなら限定したほうがセキュリティは高まります。
最後の行に以下のように追記します。

*@example.com example._domainkey.example.com

複数ユーザーを追加する場合や、複数ドメインがある場合は、複数行で追記してください。

/etc/opendkim.conf」の以下の項目が対応しています。

SigningTable refile:/etc/opendkim/SigningTable

OpenDKIMのTrustedHosts設定

TrustedHostsで信頼できるホストを設定します。
ここに追加したホストの場合に署名を行います。

# vi /etc/opendkim/TrustedHosts

デフォルトで追加されている以下のものは必須と言えます。(自分のサーバー内のため)

127.0.0.1
::1

これ以外に追記するとなると、中継サーバを利用している場合などです。同一サーバ内でメールサーバが完結している場合は特に追記する必要はありません。
ちなみにCIDRやホスト名の追加にも対応しています。

/etc/opendkim.conf」の以下の項目が対応しています。

ExternalIgnoreList refile:/etc/opendkim/TrustedHosts

opendkim.confの設定

いよいよOpenDKIM本体の設定ファイルです。

公式の解説があるので詳しくはそちらをご覧ください。

一応バックアップを取ります。

# cp /etc/opendkim.conf /etc/opendkim.conf.org
# vi /etc/opendkim.conf

以下のサイトに設定例が書いてありますが、今回はマルチドメインを想定しているので設定方法が異なります。
OpenDKIM - ArchWik

具体的にはDomainはSigningTableを利用する場合は無視されます。KeyFileもKeyTableが有効な場合は無視される、といった具合です。
基本的には無視されるオプションを変更する意味はないですが、マルチドメインであることをわかりやすくするために、シングルドメイン用の設定をあえてコメントアウトします。

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

Selector        default
↓
# Selector        default

ちなみにDomainはデフォルトではコメントアウトされています。
そしてマルチドメイン用の設定をします。

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

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

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

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

refile:」という記述ですが、解説によってはそのまま記述していますが、私の環境では以下のエラーが出て使えませんでした。公式の解説によると「refile:」は正規表現を利用した指定方法とのこと。

以下はデフォルトで設定されいますが、大切な項目なので一応確認しておいてください。

Socket                  inet:8891@localhost
UserID                  opendkim

これでopendkimの設定は完了です。
早速起動してみます。

# /etc/init.d/opendkim start

opendkimの自動起動を確認、自動起動を有効にする。

# chkconfig --list opendkim
# chkconfig opendkim on

DKIMとpostfixとの連携

OpenDKIMの設定が完了したのでpostfixと連携します。
メールフィルターでOpenDKIMのソケットを経由するように設定します。
具体的にはUnixソケットをlistenします。

# vi /etc/postfix/main.cf

記述する場所はどこでもいいですが、ファイルの最後に追記しました。

# OpenDKIM用
smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = unix:/run/opendkim/opendkim.sock

smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

これでメールはOpenDKIMのソケットを経由するようになります。
設定が完了したらpostfixを再起動します。

# /etc/init.d/postfix restart

以上でDKIMの設定が完了しました。

試しにGmailのアカウントにメールを送信したところ、ヘッダーの情報に以下のように記述されていました。

DKIM-Filter: OpenDKIM Filter v2.11.0 mail.example.com 6AB4AAAD7D9

OpenDKIMが有効になっています。


DMARC (Domain-based Message Authentication, Reporting, and Conformance)を利用する

DMARCとはDomain-based Message Authentication, Reporting, and Conformanceの略です。なんのことやらわかりませんねw
簡単に言えば上で設定したSPFとDKIMを組み合わせて補強した技術です。具体的にはSPFとDKIMで認証が失敗した際の扱いを決めたり、認証の成否をレポートメールで受け取ることが可能になります。レポートを見ればメールの利用状況を簡単に把握することができます。
Gmailが導入を推奨している技術です。

Googleの以下のページで丁寧にまとまっています。

DMARC について - G Suite 管理者 ヘルプ
DMARC を有効にする - G Suite 管理者 ヘルプ

では実際に設定をしていきます。
DMARCもDNSへ記述することで設定を行います。
Googleの解説を拝借すると以下のようになります。

DMARC TXT レコード

v=DMARC1(必須)

プロトコルのバージョン

p=reject(必須)

ドメインでの不審なメールの処理方法

none メールに対して何もせずに、日次レポートに不審なメールを記録する。
quarantine 迷惑メールに分類して保持し、処理する。
reject 受信者に送信されないようにメールをキャンセルする。

pct=20

DMARC ポリシーを適用する不審なメールの割合を設定します。不審なメールとは、DMARC 認証が通らなかったメールのことです。デフォルト値は100です。

rua=mailto:aggrep@example.com

集計レポートの報告先 URI(Uniform Resource Identifier)。ドメインの DMARC アクティビティに関するレポートを受け取るには、このオプションを使用して独自のメールアドレスを指定します。

sp=reject

メインドメインのサブドメインからのメールに関するポリシーを設定します。サブドメインに別の DMARC ポリシーを適用する場合はこのオプションを使用します。使用できる値は p タグと同じです。

aspf=r

SPF(ASPF)の調整モードを設定して、メールの情報が SPF 署名とどの程度一致する必要があるかを定義します。デフォルトは relaxed です。

r relaxed は部分一致(ドメイン内のサブドメインなど)を許可します。
s strict の場合は完全に一致する必要があります。
reject 受信者に送信されないようにメールをキャンセルする。

では実際に設定します。
私の場合はDKIMの設定の直下に追加しました。

# vi /var/named/example.com.hosts
_dmarc.example.com.	IN	TXT	"v=DMARC1; p=quarantine; pct=100; rua=mailto:info@example"

シリアル番号を進めて再起動します。

# /etc/init.d/named restart

チェックします。

$ dig txt _dmarc.example.com

以下のように応答があれば正しく設定できています。

;; ANSWER SECTION:
_dmarc.example.com.    38400   IN      TXT     "v=DMARC1\; p=quarantine\; pct=100\; rua=mailto:info@example.com"

DMARCのレポートは送信したドメインごとにzip形式で送られてきます。
以下のものはGmailのレポート例です。

<?xml version="1.0" encoding="UTF-8" ?>
<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <email>noreply-dmarc-support@google.com</email>
    <extra_contact_info>https://support.google.com/a/answer/2466580</extra_contact_info>
    <report_id>12647404983077268418</report_id>
    <date_range>
      <begin>1557014400</begin>
      <end>1557100799</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>oxynotes.com</domain>
    <adkim>r</adkim>
    <aspf>r</aspf>
    <p>quarantine</p>
    <sp>quarantine</sp>
    <pct>100</pct>
  </policy_published>
  <record>
    <row>
      <source_ip>153.122.40.105</source_ip>
      <count>4</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>pass</dkim>
        <spf>pass</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>oxynotes.com</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>oxynotes.com</domain>
        <result>pass</result>
        <selector>oxynotes</selector>
      </dkim>
      <dkim>
        <domain>oxynotes.com</domain>
        <result>pass</result>
        <selector>oxynotes</selector>
      </dkim>
      <spf>
        <domain>oxynotes.com</domain>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
</feedback>

auth_resultsのdkimとspfの項目がpassとなっています。失敗した場合はfailと表示されます。
今回はレポートを受け取る側ですが、自分のメールサーバがメールを受信した際に送信サーバへレポートを送ることもできます。それをサポートしているのがOpenDMARCというパッケージです。送信時には関係ないのでこのページでは解説しませんが、設定する場合は以下のページを参照してください。

OpenDMARC - ArchWiki


Let's Encryptを利用してオレオレ証明書からの脱却

以前投稿したメールサーバを構築する方法でオレオレ証明書を利用したSSL通信の方法を解説しました。
しかし今やLet’s Encryptを利用すれば、無料でSSL証明書を利用できます。独自で有料のSSL証明書を用意できないのであれば、利用しない理由はありません。

Let’s Encryptについては過去の投稿で詳しくまとめたのでそちらをご覧ください。

では早速設定を開始します。

# ./certbot-auto certonly --webroot -w /var/www/html/example -d mail.example.com -m info@example.com --agree-tos -n

webサーバも運用している設定で「--webroot -w /var/www/html/example」とweb用の公開フォルダのルートディレクトリを指定。
-d」でドメインの指定。
-m」でトラブル時の通知用アドレスを指定。
--agree-tos -n」で証明書の利用規約への署名を省略。

これでmail.example.comに接続し、確認用のファイルを作成し、外部から確認が取れればめでたく証明書の発行となるわけです。

ちなみに、このオプションを利用するにはポート80とポート443が空いている必要があります。また、nginxでリバースプロキシを設定している場合はそちらも忘れずに設定してください。

# vi /etc/nginx/nginx.conf

SSL用の設定

        listen 443 ssl;
        server_name example.net mail.example.com;

リバースプロキシ用の設定

        listen 8080;
        server_name example.net mail.example.com;

リダイレクト用の設定

        listen       80;
        server_name example.net mail.example.com;
# /etc/init.d/nginx restart

この例はあくまでサンプルです。port 443しか利用してなければ、そのserver_nameだけでも構いません。
その他にもよくある失敗例がiptablesによるパケットフィルタリングです。普通にWebサーバとして運用しているならポートは空いていると思いますが、失敗する場合は再度設定を見直してください。

どうしてもうまくいかない場合は以下のように検証時に作られるディレクトリにファイルを作成して外部からアクセスできるか調べてみてください。

# vi /var/www/html/example/.well-known/acme-challenge/index.html

ファイルへは「Let's Encrypt Test」とでも入力してアクセスしてみてください。

postfixの設定

作成した鍵をpostfixに設定します。

# vi /etc/postfix/main.cf
smtpd_tls_cert_file = /etc/pki/postfix/postfix.pem
smtpd_tls_key_file = /etc/pki/postfix/postfix_noenc.key
↓
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem

以下追加

# postfix 2.3移行より必要になった
smtp_tls_CAfile = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtp_tls_security_level = may

設定が完了したら再起動して反映させます。

# /etc/init.d/postfix restart

このページではマルチドメイン用の設定を解説していましたがpostfixではsni対応していないので複数証明書を設定する必要はありません。

dovecotの設定

せっかくSSL証明書を取得したので、メールサーバへのログイン時にも利用します。

# vi /etc/dovecot/conf.d/10-ssl.conf
# sukegra用
ssl_cert = </etc/pki/postfix/postfix.pem
ssl_key = </etc/pki/postfix/postfix_noenc.key
↓
# sukegra用
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem

以下は追記。

# POODLE SSL 3.0 脆弱性問題 (CVE-2014-3566) 対策
# https://access.redhat.com/ja/solutions/1379503対策
ssl_protocols = !SSLv2 !SSLv3

設定が完了したらDovecotを再起動します。

# /etc/init.d/dovecot restart

ちなみにCentos6系ではTLS通信サポートしてないっぽいです。
よって以下の設定はコメントアウトしてSSLで通信にしました。

# ssl_protocols = !SSLv2 !SSLv3

以上で無事にLet's Encryptを利用したSSL通信が可能になりました。


cronで証明書の自動更新とサービスの再起動を設定

crontabで自動更新を行います。今回の例ではhttpサーバとメールサーバの両方でLet's Encryptの証明書を利用していることを想定しています。

# vi /etc/crontab
0 5 * * * root /root/certbot-auto renew --post-hook "service nginx restart;service postfix restart;service dovecot restart" >/dev/null 2>&1

毎朝五時頃に実行。出力はいらないよという設定です。

オプションのpost-hookは証明書が更新された際に一度だけ実行されるコマンドを記述します。例のように;で区切れば複数のサービスを再起動することができます。
今回は使いませんが、更新作業の前に実行されるpre-hook、個々の証明書が更新されるごとに実行されるdeploy-hookといったオプションの存在します。証明書の更新日時をフラグに対応するサービスだけを再起動したり、更新された証明書の情報をメールで通知したりといったスクリプトと組み合わせることもできます。


以上でメールサーバのセキュリティを向上させる方法について解説しました。
Gmailが推奨するこれらの認証技術ですが、導入すればメールサーバのセキュリティは確実に向上します。

ただし、導入には一定の知識が必要で、ユーザー管理にも手間がかかります。
GMOのメール障害の例にもあるように、とばっちりでメールが届かなくなることもありえます。

さまざまな状況を考慮すると、セキュリティに配慮したメールサーバを維持することの難しさを感じます。
解説しておいてなんですが、これだけの労力を払うならG Suite等のサービスを利用したほうが現実的です。

ただし、最近あったoffice 365の障害のようなこともあるので、悩ましい限りです。


現在のページを共有する



現在のページに関連する記事

Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 GMO系列のホスティングサービスでGmailへメールが送信できない不具合が発生中
Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 BIND DNS サーバの正引き用ゾーンファイルと、逆引き用ゾーンファイルの作成方法
Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 IPアドレスとドメインを結びつける、DNSサーバの役割と名前解決の仕組み
Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 DNS Amp攻撃の解説と、踏み台にされないためのBIND DNSの設定
Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 BIND DNSで行う名前解決と、各種ネットワークの設定
Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 BINDで構築したDNSサーバと、各種ネットワークの動作確認
Gmailに学ぶ「セキュリティに配慮したメールサーバを構築する方法」 レジストリへの権威ネームサーバの登録と、名前解決に関するネットワークの設定

おすすめの記事

Web制作の自由度をフレームワークレベルまで高めたCorvid by Wix 

Web制作の自由度をフレームワークレベルまで高めたCorvid by Wi…

Googlebotを手懐ける!robots.txtの書き方とrobots.txtテスターの使い方

Googlebotを手懐ける!robots.txtの書き方とrobots.txtテスター…

Apacheのmod_rewriteモジュールの使い方を徹底的に解説

Apacheのmod_rewriteモジュールの使い方を徹底的に解説

公式ドキュメントよりも詳しいTinyMCEの使い方(基本編)

公式ドキュメントよりも詳しいTinyMCEの使い方(基本編)

エンティティとデコード用プラグイン「Entity Decode Button」を作成しました

エンティティとデコード用プラグイン「Entity Decode Button」…

Linuxの基本の基本。Linuxの基本的なディレクトリ構成

Linuxの基本の基本。Linuxの基本的なディレクトリ構成

WordPressの最速キャッシュを探せ!APC、memcached、Transients APIを比較

WordPressの最速キャッシュを探せ!APC、memcached、Transients…

lazysizesの使い方を通して学ぶ、画像の遅延読み込みとレスポンシブイメージの基本

lazysizesの使い方を通して学ぶ、画像の遅延読み込みとレスポン…

開発の最前線でクリエイター・エンジニアに必要なプログラミング言語

開発の最前線でクリエイター・エンジニアに必要なプログラミン…


コメントを残す

コメントは認証制のため、すぐには反映されません。

プログラミングに関する質問は「日本語でプログラミングの悩みを解決するQ&Aサイト sukegra」をご利用ください。