手当たり次第に書くんだ

飽きっぽいのは本能

Redmine のメール送信で certificate verify failed が出る理由 – SMTP、CA、証明書チェーンの確認

Redmine からメールを送信するときに certificate verify failed が出る場合、画面上は Redmine のエラーに見えます。しかし、実際に起きているのは Redmine が接続した SMTP サーバーの TLS 証明書を、Redmine 側の実行環境が正しく検証できていないという問題です。

ここで重要なのは、Redmine、Ruby、OS、コンテナ、SMTP サーバー、CA 証明書を分けて考えることです。Redmine の設定だけを眺めても原因は見えにくく、逆に OS の信頼ストアだけを直しても、コンテナ内の Redmine には反映されていないことがあります。

エラーが示していること

Redmine のメール送信テストや通知メールの送信時に、次のようなエラーが出ることがあります。

メール送信中にエラーが発生しました
SSL_connect returned=1 errno=0 peeraddr=192.0.2.10:25 state=error:
certificate verify failed (unable to get local issuer certificate)

unable to get local issuer certificate は、接続先の証明書を発行した CA を、接続元が信頼できていないことを示します。Redmine が悪いというより、Redmine を動かしている Ruby の OpenSSL が、SMTP サーバーの証明書チェーンを最後まで検証できていない状態です。

Redmine だけでなく実行環境を見る

Redmine のメール送信は、Redmine 単体で完結しているわけではありません。Redmine の configuration.yml に SMTP 接続先を書き、Ruby のライブラリが TLS 接続を行い、その下で OS やコンテナ内の CA 信頼ストアが使われます。

そのため、ホスト OS に内部 CA を入れたつもりでも、Redmine をコンテナで動かしている場合は、Redmine コンテナ内に CA 証明書が入っていなければ失敗します。逆に、SMTP サーバー側の証明書チェーンに中間証明書が不足している場合は、Redmine 側をいくら触っても根本解決にはなりません。

確認する観点:

  • Redmine が接続している SMTP サーバー名とポート
  • STARTTLS、SMTPS、平文 SMTP のどれで接続しているか
  • SMTP サーバーが提示しているサーバー証明書と中間証明書
  • Redmine の実行環境に入っている CA 信頼ストア
  • 証明書の SAN と SMTP 接続先名が一致しているか

よくある原因

原因として多いのは、内部 CA 証明書が Redmine 側に配布されていないケースです。社内のメールサーバーや内部向け SMTP リレーでは、公開 CA ではなく内部 CA の証明書を使っていることがあります。その場合、Redmine の実行環境がその CA を信頼していなければ、証明書検証は失敗します。

次に多いのは、中間証明書の不足です。SMTP サーバーがサーバー証明書だけを提示し、中間証明書を正しく返していない場合、接続元は証明書チェーンを組み立てられません。ブラウザでは補完されて気づきにくいこともありますが、アプリケーションからの TLS 接続では失敗として表面化することがあります。

また、接続先名の不一致も見落としやすい点です。たとえば mail.example.internal に接続しているのに、証明書の SAN が smtp.example.internal だけであれば、CA を信頼していても検証は通りません。証明書は「信頼された CA から発行されているか」だけでなく、「接続している名前に対して発行されているか」も検証されます。

安易に検証を無効化しない

Redmine では、SMTP 設定の中で OpenSSL の検証モードを変更できます。検証を無効化すれば、一時的にメール送信テストが通ることはあります。

default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: mail.example.internal
      port: 25
      domain: redmine.example.internal
      openssl_verify_mode: none

ただし、これは根本対応ではありません。openssl_verify_mode: none は、通信相手の証明書を検証しない方向へ寄せる設定です。原因の切り分けや一時的な疎通確認として使う場面はあり得ますが、恒久運用の前提にすべきではありません。

本来の対応は、SMTP サーバー側で正しい証明書チェーンを提示し、Redmine 側の実行環境に必要な CA 証明書を配布し、接続先名と証明書の SAN を一致させることです。検証を無効化して動かすのではなく、検証できる状態に直すのが基本です。

コンテナ環境では CA の配置先を間違えやすい

Redmine を Docker、Podman、Kubernetes などで動かしている場合、CA 証明書の配置先には注意が必要です。ホスト OS の /etc/ssl/certs/usr/local/share/ca-certificates を更新しても、Redmine コンテナの中に同じ CA が入っているとは限りません。

コンテナイメージの中に CA を追加するのか、起動時にマウントするのか、Kubernetes の Secret / ConfigMap として配布するのか。ここは運用設計として決める必要があります。証明書更新のたびに手作業でコンテナ内へコピーするような運用にすると、いつか更新漏れが起きます。

公開証明書と内部 CA の使い分け

SMTP サーバーが外部からも利用されるなら、公開 CA の証明書を使う方が扱いやすいことがあります。Redmine 側へ独自 CA を配布しなくても、一般的な実行環境の信頼ストアで検証できるためです。

一方で、完全に内部向けの SMTP リレーであれば、内部 CA を使う設計もあります。その場合は、内部 CA の発行、配布、更新、失効、監視まで含めて設計しなければなりません。証明書の発行だけを見ていると運用が抜けます。

Redmine のメール送信エラーは小さな事象に見えますが、実際には証明書運用の境界が見える場所です。SMTP サーバー側が何を提示するのか、Redmine 側が何を信頼するのか、その責任分界を明確にしておく必要があります。

確認するときの順序

まず、Redmine が実際に接続している SMTP ホスト名とポートを確認します。設定ファイル上の名前と、証明書に含まれる SAN が一致しているかを見ます。次に、SMTP サーバーが提示する証明書チェーンを確認し、中間証明書が不足していないかを見ます。

そのうえで、Redmine が動いている環境の CA 信頼ストアを確認します。コンテナであればコンテナ内、Kubernetes であれば Pod 内、仮想マシンであればその OS 内で確認します。ホスト側で確認して終わりにしないことが重要です。

最後に、暫定回避として検証無効化を入れている場合は、それを恒久設定にしないようにします。原因を特定したら、CA 配布、証明書チェーン、接続先名のいずれかを修正し、検証を有効に戻した状態でメール送信できることを確認します。

参考
書籍
参考書籍

暗号技術入門 第 3 版 秘密の国のアリス

公開鍵暗号、電子署名、証明書など、TLS や内部 PKI の前提になる暗号技術を確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

参考

参考:

関連する記事

あわせて読みたい:

Redmine のメール送信で certificate verify failed が出る理由 – SMTP、CA、証明書チェーンの確認

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る