AlmaLinux 10にインストールされているPostfixで、SSL/TLSを使用して通信の暗号化を有効化する方法です。
本記事では、下記の手順で構築したPostfix環境に対して追加で通信の暗号化設定を行っていきます。
【AlmaLinux 10】Postfix + SMTP-AUTH + Dovecotでメールサーバを構築する方法
※Dovecotの通信暗号化(POP3S/IMAPS)の方法は、以下の記事で解説しています。
【AlmaLinux 10】DovecotをSSL/TLSで通信暗号化する方法
※コマンドは一般ユーザーから「sudo」を実行する形式で記載しています。行頭のプロンプト記号は省略しているため、そのままコピー&ペーストして実行可能です。
作業工程
作業工程は下記のとおりです。
- SSL/TLS証明書の事前準備
- Postfix設定
- /etc/postfix/main.cf 設定
- /etc/postfix/master.cf 設定(587番・465番ポートの暗号化)
- 設定反映
- 動作確認
- 平文認証の拒否確認(587番ポート)
- コマンドライン(openssl)によるSSL/TLS接続テスト
- Let's Encrypt証明書更新時の自動反映設定
SSL/TLS証明書の事前準備
今回の手順では、Let's Encryptで取得したSSL/TLS証明書を使用しています。
証明書の取得方法については、下記のページを参考にしてください。
【AlmaLinux9】Let’s EncryptでSSL/TLS証明書を取得する方法(Nginx + certbot)
すでにドメイン用の証明書(fullchain.pem、privkey.pem)を取得済みの場合は、この事前準備は不要です。
Postfix設定
SSL/TLS証明書を使って、外部メールサーバーとの通信やメールクライアント(Submissionポート等)からの送信時における通信を暗号化するための設定を行います。
/etc/postfix/main.cf 設定
main.cfにSSL/TLS暗号化を有効化するための設定を追加します。
cd /etc/postfix sudo cp -p main.cf main.cf_$(date +%Y%m%d-%H%M%S) sudo vi main.cf
既存の証明書設定の無効化
初期状態で設定されている自己署名証明書と秘密鍵を指定する項目の行頭に「#」をつけて無効化(コメントアウト)します。
(暗号化に関する設定をファイルの末尾にまとめて記述して管理しやすくするためです)
#smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem #smtpd_tls_key_file = /etc/pki/tls/private/postfix.key
SSL/TLS暗号化設定の追加
main.cfの末尾に、以下の通信暗号化設定を追記します。
「ドメイン名」の部分(例: mail.server-memo.net)は、ご自身の証明書を取得したFQDNに適宜読み替えてください。
# TLS/SSL暗号化設定(受信・サーバー側)
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_loglevel = 1
smtpd_tls_cert_file = /etc/letsencrypt/live/ドメイン名/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/ドメイン名/privkey.pem
smtpd_tls_session_cache_database = lmdb:${data_directory}/smtpd_scache
# TLS/SSL暗号化設定(外部送信・クライアント側)
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = lmdb:${data_directory}/smtp_scache
TLSセッションキャッシュの指定について(LMDB形式への変更)
AlmaLinux 9以前の解説記事では、セッションキャッシュの保存先として「btree:${data_directory}/smtpd_scache」と指定するのが一般的でした。
しかし、AlmaLinux 10(RHEL 10系)では従来のBerkeley DB(libdb)が完全に削除されたため、「btree:」や「hash:」を指定すると「fatal: unsupported dictionary type: btree」というエラーが発生してPostfixが起動できなくなります。
そのため、AlmaLinux 10では標準データベース形式である「lmdb:」を使用し、サーバー用(受信側)として 「lmdb:${data_directory}/smtpd_scache」 を、クライアント用(送信側)として 「lmdb:${data_directory}/smtp_scache」 を指定してください。
※「${data_directory}」は自動的に「/var/lib/postfix」に展開され、Postfixの「tlsmgr」プロセスが必要に応じてデータベースファイル(.lmdb)を自動生成・管理します。
各パラメータの解説
- smtpd_tls_security_level = may: 25番ポートで日和見暗号化(相手がSTARTTLSに対応していれば暗号化通信を行い、非対応なら平文で受信)を有効にします。
- smtpd_tls_auth_only = yes: 暗号化(TLS)されていない平文通信でのSMTP認証(パスワード送信)を禁止し、情報漏洩を防ぎます。
- smtpd_tls_loglevel = 1: TLS接続のハンドシェイク成功ログをメールログに記録します。
- smtpd_tls_cert_file / smtpd_tls_key_file: Let's Encryptで取得した証明書と秘密鍵のフルパスを指定します。
- smtp_tls_security_level = may: Postfixから外部メールサーバー(Gmail等)へメールを送信する際にも、相手がSTARTTLSに対応していれば自動的に暗号化通信を行う設定です。
【補足】古い暗号化プロトコル(SSLv3 / TLS 1.0 / TLS 1.1)の無効化について
古い解説記事などでは「smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1」のような個別除外設定が紹介されていることがあります。
しかし、AlmaLinux 10(RHEL 10系)ではOS全体の「システム暗号化ポリシー(crypto-policies)」によって、脆弱なプロトコル(SSLv3、TLS 1.0、TLS 1.1)はOSレベルでデフォルト無効化されています。
そのため、Postfix側で個別に除外パラメータを記述しなくても、自動的に安全な「TLS 1.2」および「TLS 1.3」のみが使用されます。
/etc/postfix/master.cf 設定
メールクライアントからのメール送信を受け付けるポートで、SSL/TLSによる通信暗号化を有効化します。
sudo cp -p master.cf master.cf_$(date +%Y%m%d-%H%M%S) sudo vi master.cf
587番ポート(Submission / STARTTLS必須化)の設定
Submission(587番)ポート経由のメール送信では、平文送信を一切許可せずSSL/TLS暗号化を「必須(encrypt)」にする設定を行います。
「submission」ブロック内の「-o smtpd_tls_security_level=encrypt」の行頭にある「#」を削除して有効化します。
submission inet n - n - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
※各パラメータの前には必ず半角スペース(インデント)が必要です。
【推奨】465番ポート(SMTPS)の有効化
現在のメール通信規格(RFC 8314)では、接続開始時からSSL/TLS暗号化を行う「465番ポート(SMTPS)」の利用が推奨されており、iPhoneやMac、各種メールアプリでも標準設定として広く使われています。
そのため、587番ポートとあわせて465番ポートも有効化しておくことをおすすめします。
「master.cf」内にある「submissions」(末尾に「s」が付くブロック)の行頭の「#」を削除して有効化します。
submissions inet n - n - - smtpd -o syslog_name=postfix/submissions -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
※465番ポートを利用する場合は、ファイアウォール(firewalld)で通信を許可(ポート開放)しておきます。
sudo firewall-cmd --permanent --add-port=465/tcp sudo firewall-cmd --reload
設定反映
設定ファイルに文法上の誤りがないかチェックし、問題がなければPostfixを再起動して設定を反映させます。
sudo postfix check sudo systemctl restart postfix
動作確認
暗号化の設定が正しく反映されているか、サーバー内部からコマンドを使って動作確認を行います。
平文での認証が拒否されることの確認(587番ポート)
前回の記事「【AlmaLinux 10】Postfix + SMTP-AUTH + Dovecotでメールサーバを構築する方法」では、平文のまま587番ポートへ接続した際に「250-AUTH PLAIN LOGIN」が表示され、そのまま認証(AUTH LOGIN)を行うことができました。
暗号化必須(smtpd_tls_security_level = encrypt)にしたことで、平文では認証を受け付けなくなっているか「nc」コマンドを使用して確認します。
nc 127.0.0.1 587
接続後、以下のように入力します(赤字部分を入力します)。
220 mail.server-memo.net ESMTP EHLO localhost 250-mail.server-memo.net 250-PIPELINING 250-SIZE 20971520 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN AUTH LOGIN 530 5.7.0 Must issue a STARTTLS command first QUIT 221 2.0.0 Bye
EHLOの応答に「250-AUTH」が表示されず「250-STARTTLS」が表示され、直接「AUTH LOGIN」を入力しても「530 5.7.0 Must issue a STARTTLS command first(先にSTARTTLSで暗号化を行ってください)」と正しく拒否されることが確認できます。
コマンドライン(openssl)によるSSL/TLS接続テスト
続いて、「openssl」コマンドを使って暗号化接続が正常に行えるかテストします。
587番ポート(STARTTLS)の確認
openssl s_client -connect 127.0.0.1:587 -starttls smtp
コマンド実行後、画面に証明書情報(Let's Encryptの情報)とともに「Verification: OK」や「SSL-Session:」「250 CHUNKING」などが表示されれば、STARTTLSによる暗号化ネゴシエーションは成功です。
「read R BLOCK」で待機状態になったら、「QUIT」 と入力してEnterを押し、接続を終了します。
Connecting to 127.0.0.1
CONNECTED(00000003)
Can't use SSL_get_servername
depth=3 C=US, O=Internet Security Research Group, CN=ISRG Root X2
verify return:1
depth=2 C=US, O=ISRG, CN=Root YE
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=YE1
verify return:1
depth=0 CN=mail.server-memo.net
verify return:1
---
Certificate chain
0 s:CN=mail.server-memo.net
i:C=US, O=Let's Encrypt, CN=YE1
### 中略 ###
---
SSL handshake has read 4008 bytes and written 1634 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Server public key is 256 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
250 CHUNKING
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
### 中略 ###
Start Time: 1793799346
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
read R BLOCK
QUIT
221 2.0.0 Bye
closed
465番ポート(SMTPS)の確認(※465番を有効にした場合)
openssl s_client -connect 127.0.0.1:465
接続直後にSSLハンドシェイクが完了し、「read R BLOCK」に続いて「220 mail.server-memo.net ESMTP」と表示されれば正常です。
確認後、「QUIT」 と入力してEnterを押し、接続を終了します。
Connecting to 127.0.0.1
CONNECTED(00000003)
Can't use SSL_get_servername
depth=3 C=US, O=Internet Security Research Group, CN=ISRG Root X2
verify return:1
depth=2 C=US, O=ISRG, CN=Root YE
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=YE1
verify return:1
depth=0 CN=mail.server-memo.net
verify return:1
---
Certificate chain
0 s:CN=mail.server-memo.net
i:C=US, O=Let's Encrypt, CN=YE1
### 中略 ###
---
SSL handshake has read 3785 bytes and written 1601 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Server public key is 256 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
### 中略 ###
Start Time: 1793799847
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
read R BLOCK
220 mail.server-memo.net ESMTP
QUIT
221 2.0.0 Bye
closed
※メールクライアント(Thunderbird等)における暗号化接続設定は、次のステップである「DovecotのSSL/TLS暗号化(受信側)」を完了させた後、送信・受信の設定をまとめて行います。
Let's Encrypt証明書更新時の自動反映設定
Let's EncryptのSSL/TLS証明書は有効期間が90日間となっており、有効期限が残り30日以内になると自動更新(通常は約60日ごと)が行われます。
証明書が自動更新された際、Postfixに新しい証明書を無停止で再読み込みさせるため、更新フック(renewal-hooks)を利用したスクリプトを作成します。
Certbotには、証明書の更新が成功した直後にのみスクリプトを実行してくれる「/etc/letsencrypt/renewal-hooks/deploy/」という仕組みが用意されています。
ここにスクリプトを配置しておくことで、「実際に新しい証明書が正常に発行・更新された時だけ」 Postfixをリロードさせることができます。
cd /etc/letsencrypt/renewal-hooks/deploy/ sudo vi reload_postfix.sh
スクリプトの内容は以下のとおりです。
「restart」ではなく「reload」を使用することで、処理中のメールセッションを切断することなくサービス無停止で新しい証明書を再読み込みできます。
#!/bin/bash systemctl reload postfix
スクリプトに実行権限を付与します。
sudo chmod 755 reload_postfix.sh
まずは、作成したスクリプトを直接実行し、Postfixが正常にリロードできるか単体テストを行います。
sudo ./reload_postfix.sh
Postfixが正常にリロードされたかは、メールログで確認できます。
sudo grep 'postfix/master.*reload' /var/log/maillog | tail -n 5
ログの出力例です。
スクリプトを実行した時間にreloadのログが記録されていることを確認してください。
Nov 4 17:04:58 localhost postfix/master[2220]: reload -- version 3.8.5, configuration /etc/postfix
スクリプト単体での動作に問題がなければ、次にcertbotのドライラン(更新テスト)を実行し、証明書更新時にこのフックスクリプトが自動で呼び出されるか連携テストを行います。
対象の証明書のみを指定するために「--cert-name」と、ドライラン時にも実際にデプロイフックを実行させるために「--run-deploy-hooks」を指定します。
sudo certbot renew --cert-name ドメイン名 --dry-run --run-deploy-hooks
エラーが出ずに「Congratulations, all simulated renewals succeeded」と表示されれば、更新シミュレーションは成功です。
以下は、実行時のログ出力例です。
$ sudo certbot renew --cert-name mail.server-memo.net --dry-run --run-deploy-hooks Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/mail.server-memo.net.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Simulating renewal of an existing certificate for mail.server-memo.net - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/mail.server-memo.net/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
最後にメールログを確認し、Certbotのテストによってフックスクリプトが呼び出され、Postfixが正常にリロードされたことを確認します。
sudo grep 'postfix/master.*reload' /var/log/maillog | tail -n 5
ログの出力例です。
ドライラン実行時刻のタイムスタンプでリロードログが出力されていれば成功です。
Nov 5 23:26:32 localhost postfix/master[2220]: reload -- version 3.8.5, configuration /etc/postfix
このようにリロードログが確認できれば、証明書更新時の自動反映設定はすべて完了です。
※もし「--dry-run」実行時に「Connection reset by peer」等の接続エラーが発生する場合は、Let's Encryptのテスト用(ステージング)サーバー側で一時的な通信制限や障害が発生している可能性があります。
その場合は時間をおいて再度試してみてください。
以上で、AlmaLinux 10のPostfixにおけるSSL/TLS通信暗号化の設定はすべて完了です。
【次のステップ】Dovecotの通信暗号化(POP3S / IMAPS)
Postfix(送信側)の暗号化が完了しましたが、このままではDovecot(受信側)の通信が平文のままです。
メール受信時(POP3 / IMAP)にパスワードやメール本文が生の状態でネットワークに流れてしまうのを防ぐため、必ず続けて下記の記事を参考にDovecotの通信暗号化を実施してください。
Dovecotの暗号化が完了した段階で、Thunderbirdなどのメールクライアントを使った送受信の暗号化設定をまとめて行います。
コメント