2026年7月6日
2026年7月6日
メールの暗号化(TLS・STARTTLS)設定方法:ポートの選び方からPostfix・Dovecot・WordPressの設定まで
メールの通信を暗号化するには、メールアプリとサーバーの間は「暗黙のTLS(465番・993番)」か「STARTTLS(587番など)」で接続し、サーバー同士の25番では相手が対応していればSTARTTLSを使う、という分け方で設定します。この記事では、TLSとSTARTTLSの違いとポートの選び方、Postfix・Dovecotでの設定、openssl s_client とログでの確認方法、WordPressからSMTPで送るときの暗号化の指定までを説明します。
TLSとSTARTTLSの違い
どちらも通信をTLSで暗号化する点は同じで、違うのは「いつ暗号化を始めるか」です。
- 暗黙のTLS(Implicit TLS): 接続した瞬間からTLSで通信します。最初から暗号化されているため、途中で暗号化を妨害される余地がありません。メールアプリでは「SSL/TLS」と表示されることが多い方式です。
- STARTTLS: 最初は平文で接続し、サーバーが対応を表明したら
STARTTLSコマンドで暗号化に切り替えます。同じポートで暗号化あり・なしの両方を扱えるのが利点ですが、通信の途中にいる攻撃者が対応の表明を消すと、暗号化されないまま進んでしまうことがあります(STARTTLSの除去攻撃)。
この弱点から、メールアプリとサーバーの間については、暗黙のTLSを優先することがRFC 8314で推奨されています。ただし、587番のSTARTTLSも広く使われており、サーバー側で「TLSを確立するまで認証させない」設定にしておけば、パスワードが平文で流れることは防げます。
ポートの選び方
| 用途 | ポート | 方式 |
|---|---|---|
| メールアプリからの送信 | 465 | 暗黙のTLS |
| メールアプリからの送信 | 587 | STARTTLS |
| メールの受信(IMAP) | 993 | 暗黙のTLS |
| メールの受信(POP3) | 995 | 暗黙のTLS |
| サーバー同士の配送 | 25 | STARTTLS(相手が対応していれば) |
IMAPの143番やPOP3の110番もSTARTTLSで使えますが、993番・995番があれば、平文のポートは閉じてしまうほうが設定の誤りを防げます。
サーバー同士の25番は事情が異なります。インターネット上のすべてのメールサーバーがTLSに対応しているわけではないため、公開しているMXで「TLSでなければ受け付けない」設定にすると、対応していない相手からのメールを受け取れなくなります。そのため25番は「相手が対応していればTLSを使う」設定にし、暗号化を強制したい場合は、MTA-STSやDANEといった、配送先がTLS必須であることを公開する仕組みを別に使います。
証明書を用意する
メールアプリや相手のサーバーは、証明書のホスト名を確認します。mail.example.com のように、メールアプリに設定するホスト名とMXのホスト名を含む証明書を用意します。Let's Encryptを使う場合は、更新後にPostfixとDovecotを読み込み直すよう、--deploy-hook "systemctl reload postfix dovecot" を付けて取得しておきます。中間証明書を含む fullchain.pem を指定しないと、一部のクライアントで検証に失敗します。
Postfixの設定
作業前に /etc/postfix/ をバックアップします。main.cf の主な項目は次のとおりです。
# 受信側(他のサーバーやメールアプリからの接続)
sudo postconf -e 'smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem'
sudo postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem'
sudo postconf -e 'smtpd_tls_security_level = may'
sudo postconf -e 'smtpd_tls_auth_only = yes'
sudo postconf -e 'smtpd_tls_loglevel = 1'
sudo postconf -e 'smtpd_tls_received_header = yes'
# 送信側(他のサーバーへ配送するとき)
sudo postconf -e 'smtp_tls_security_level = may'
sudo postconf -e 'smtp_tls_loglevel = 1'
smtpd_tls_security_level = mayは、25番で相手が求めればSTARTTLSを使う設定です。前の節の理由から、公開しているMXではencryptにしません。smtpd_tls_auth_only = yesは、TLSを確立する前のSMTP認証を受け付けない設定です。パスワードが平文で流れることを防ぎます。smtp_tls_security_level = mayは、配送先が対応していればTLSで送る設定です。特定の相手にだけ暗号化を強制したい場合は、smtp_tls_policy_mapsで宛先ごとに指定します。全体をencryptにすると、TLSに対応していない相手に届かなくなります。loglevel = 1にすると、TLSで接続したかどうかがログに残り、後の確認に使えます。
古いTLSのバージョンを無効にするには、Postfix 3.6以降なら smtpd_tls_protocols = >=TLSv1.2 の形で書けます。それより古い版では !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 のように除外する形で書きます。postconf mail_version で版を確認してから設定してください。なお、25番のサーバー同士の通信で古い版を禁止すると、古いサーバーとは暗号化なしの通信になることがあるため、まずはメールアプリ向けのポートから絞るのが穏当です。
465番(暗黙のTLS)を有効にする
master.cf で、465番の定義を有効にします。587番の設定は「Postfix+DovecotでIMAPメールサーバーを構築する手順」で扱った内容と同じです。
submissions inet n - y - - smtpd
-o syslog_name=postfix/submissions
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
smtpd_tls_wrappermode=yes が、接続直後からTLSで通信する指定です。サービス名は、新しい環境では submissions、古い環境では smtps と書かれています。master.cf にコメントアウトされた行があれば、その名前に合わせます。変更後は sudo postfix check で文法を確認し、sudo systemctl reload postfix で反映し、ファイアウォールで465番を開けます。
Dovecotの設定
Dovecotでは、TLSを必須にし、平文のポートを閉じます。以下は2.3系の書き方です。2.4系では証明書の項目が ssl_server_cert_file・ssl_server_key_file に変わるなど名前が違うため、dovecot --version で版を確認し、公式ドキュメントに合わせます(2026年10月現在)。
# 10-ssl.conf
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_min_protocol = TLSv1.2
# 10-master.conf(service imap-login の中)
inet_listener imap {
port = 0
}
ssl = required は、TLSなしの接続では認証させない設定です。port = 0 で143番を閉じ、993番だけを使います。
暗号化されているか確認する
openssl s_client で接続を試す
別のマシンから、各ポートに接続して証明書と暗号化の状態を確かめます。
# 25番・587番(STARTTLS)
openssl s_client -connect mail.example.com:25 -starttls smtp -servername mail.example.com
openssl s_client -connect mail.example.com:587 -starttls smtp -servername mail.example.com
# 465番・993番(暗黙のTLS)
openssl s_client -connect mail.example.com:465 -servername mail.example.com
openssl s_client -connect mail.example.com:993 -servername mail.example.com
出力の Verify return code: 0 (ok) で証明書の検証が通ったこと、Protocol や New, TLSv1.3 などの行で使われたTLSのバージョンが分かります。検証に失敗する場合は、証明書のホスト名、中間証明書の不足、期限切れの順に確認します。手元のネットワークで25番の外向き通信が止められていることもあるため、25番だけつながらないときはその可能性も考えます。
ログとヘッダーで確認する
smtpd_tls_loglevel = 1 にしてあれば、/var/log/mail.log に次のような行が出ます。
postfix/smtpd[...]: Anonymous TLS connection established from ...: TLSv1.3 with cipher ...
postfix/smtp[...]: Untrusted TLS connection established to ...: TLSv1.3 with cipher ...
1行目は受信、2行目は送信の記録です。送信側の Untrusted は「暗号化はしたが、相手の証明書を検証していない(またはできなかった)」という意味で、may の設定では珍しくありません。CA証明書の場所(smtp_tls_CApath など)が設定されていて検証に成功すると Trusted と記録されます。
受信したメールでは、smtpd_tls_received_header = yes によって Received ヘッダーに (using TLSv1.3 with cipher ...) のような記録が付きます。外部のメールサービスに送った場合は、受信側のメールのソースの Received ヘッダーで、自分のサーバーからTLSで届いたかを確認できます。
WordPressから送るときの指定
WordPressの wp_mail() をSMTP経由で送る場合も、暗号化の方式とポートの組み合わせを合わせます。WordPressに同梱されているPHPMailerでは、SMTPSecure に 'tls' を指定するとSTARTTLS、'ssl' を指定すると暗黙のTLSになります。名前が紛らわしいのですが、'tls' は「STARTTLSで切り替える」という意味です。SMTP用のプラグインでも同じ区別があり、587番には「TLS」、465番には「SSL」を選ぶ画面が多いものの、表記はプラグインや版によって違います。
プラグインを使わずに設定する場合は、phpmailer_init アクションを使ったmu-pluginにし、認証情報は wp-config.php の定数に置きます。
<?php
// wp-content/mu-plugins/smtp-tls.php
// wp-config.php に SMTP_USER と SMTP_PASS を define しておく
add_action( 'phpmailer_init', function ( $phpmailer ) {
if ( ! defined( 'SMTP_USER' ) || ! defined( 'SMTP_PASS' ) ) {
return;
}
$phpmailer->isSMTP();
$phpmailer->Host = 'mail.example.com';
$phpmailer->Port = 587;
$phpmailer->SMTPSecure = 'tls'; // 587 番は STARTTLS。465 番なら 'ssl'
$phpmailer->SMTPAuth = true;
$phpmailer->Username = SMTP_USER;
$phpmailer->Password = SMTP_PASS;
} );
接続エラーを避けるために、証明書の検証を無効にする設定(SMTPOptions で verify_peer を false にするなど)が紹介されていることがありますが、これでは暗号化していても接続先を確かめられません。エラーが出る場合は、Host を証明書のホスト名と一致させ、サーバーの証明書と中間証明書を直します。
まとめ
- TLSとSTARTTLSの違いは暗号化を始める時点で、メールアプリとの間は暗黙のTLS(465番・993番)が推奨されています。587番のSTARTTLSも、TLS確立前の認証を禁止すれば安全に使えます。
- サーバー同士の25番は
may(相手が対応していれば暗号化)にし、強制したい場合はMTA-STSやDANEを使います。 - Postfixは
smtpd_tls_auth_only = yesとログの設定、Dovecotはssl = requiredと平文ポートの停止が要点です。 openssl s_client、mail.log、Receivedヘッダーで、実際に暗号化されているかを確認します。- WordPressでは
SMTPSecureの'tls'がSTARTTLS、'ssl'が暗黙のTLSです。証明書の検証は無効にしません。