メールホスト名の証明書不一致によりsidekiqキューが過負荷、深刻なサイト不安定化が発生

長年 Discourse をセルフホストしており、いくつかのインスタンスをかなり強力なマシンで問題なく設定・稼働させていました。

今日、フォーラムの 1 つがダウンしていることに気づきました。当初の原因はディスク容量不足のようだったので、それを解消しました。その後、Discourse インスタンスを再起動しました。

しかし、その後も定期的にダウンし続けています。起動するたびに、sidekiq が異常に動作し、大量のメール送信ジョブが失敗しているのがすぐにわかります。これが原因で redis が大量の状態を保存しており、それがディスク容量の問題の真の原因だったと思われます。(マシンを起動できるようになったらすぐに flush を実行する予定ですが、そうしないとすぐにこのマシンの容量が不足し、flush を実行するために Discourse を起動することすらできなくなります。しかし、flush を行っても redis のディスク使用量はあまり減らないようです。)

エラーメッセージは証明書の名前の不一致に関するものを示しており、使用しているメールサーバーは内部のもので TLS や認証を必要としないため、少し驚いています。他のインスタンス (同じメール設定を使用) で確認したところ、メール送信が停止していました。メインの production ログで見られるのは 422 エラーだけですが、パスワードリセットのようなものを送信すると、sidekiq ログで同様のエラーが表示されます。

Jobs::HandledExceptionWrapper: Wrapped OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error:certificate verify failed (Hostname mismatch)

コマンドラインからメールを送信できることを確認できたので、メールサーバー自体の問題ではないようです。Discourse の設定に問題があるようです。

以下は、最近まで機能していた元のメール設定です。

DISCOURSE_SMTP_ADDRESS: outbound-relays.techservices.illinois.edu
DISCOURSE_SMTP_PORT: 25
DISCOURSE_SMTP_ENABLE_START_TLS: false

繰り返しますが、このメールサーバーは内部のもので、ユーザー名やパスワードは必要なく、これらの設定は最近まで機能していました。DISCOURSE_SMTP_OPENSSL_VERIFY_MODE を試しましたが、まだサポートされているかどうかはわかりません。いずれにしても、役に立っていません。フォーラムを設定してから追加されたと思われる新しいメール設定がいくつかありましたが、このメールサーバーの設定を考えると必要ないようです。

何か助けていただけると幸いです!現時点では、何が間違っているのか、あるいはどのように反復処理すればよいのかさえ確信が持てません。コンテナの再構築には時間がかかり、production ログのエラーメッセージには 422 エラーしか表示されず、実際の根本原因をどこで探せばよいのかわかりません。(どこかにあるはずですよね?見落としているだけだと思います。)

「いいね!」 1

アップデートとして、別のスレッドのアドバイスに従ったところ、このコマンドでDockerコンテナ内から正常にメールを送信できました。

echo message | s-nail -r "noreply@myforum.com" -s testing -S "smtp=same.email-service.com:25" my@address.com

これは、この問題が発生したときに使用していたメール設定と一致しています。また、金曜日に(必須の)コマンドラインプル経由で最新のDiscourseにアップグレードしたことも指摘しておきます。最近のコミットがこの問題を引き起こしたのではないかと疑問に思っています。

「いいね!」 2

コンテナを最後に再構築したのはいつですか?

また、Redisキューをクリアしましたか?

「いいね!」 2

金曜日の午前中だったと思います。UI経由の通常のアップデートで launcher app rebuild が必要になりました。後でsidekiqのログを確認したところ、コンテナが再構築された頃にバックログが始まったようですが、Redisのログがホストの利用可能なストレージをすべて消費して実際にダウンタイムが発生するまで約24時間かかりました。しかし、sidekiqが100%のCPU使用率で増加し続ける失敗したメールジョブを必死に再送信しようとしていたことを考えると、それ以前からフォーラムは遅かったのでしょう。

はい。

しかし、これでRedisのディスク使用量が減少しなかったことは懸念事項です。redis_data というフォルダがあり、フラッシュ後でも現在29Gのサイズです。おそらくRedisはMongoDBのように、ディスク割り当てを解放するのが難しいのでしょうか?これはマシンのディスク容量の1/3を占めるため問題になりますが、まずはメールを再び機能させることを優先して、今はその問題は後回しにします。

「いいね!」 1

デバッグ用のメモですが、Discourse が使用するのと同じコードフローを使用して、コンテナ内のコマンドラインからテストメールを送信する方法はありますか?(つまり、すでに確認済みの別のツールを使用してコマンドラインから送信するのではなく。)これはデバッグに役立ちます。現在、テストメールの送信には Web UI の操作が必要で、その後ログを調べて何がうまくいかなかったのかを突き止める必要があります。(そして、これまでのところ、サイドキックログ(テストメールフローを使用する際に作成されない)以外では、より役立つものは何も見つからず、422 エラーしか見つかっていません。)あるいは、テストメール UI でより多くのデバッグ情報が表示されるようにすることはできますか?

全体として、ほとんどの人はメールが機能した状態で Discourse をセットアップし、この段階に到達すると思いますが、招待状の送信などに必要なので、メールが機能しなくなり、突然停止した場合のデバッグ可能性は限られていると感じています。(また、このケースではリトライが非常に速いように見えるため、リトライロジックの調整が必要になるかもしれません。証明書エラーは、最初の試行から数秒後に修正される可能性は低いでしょう…)

「いいね!」 1

新しいDiscourseのインストールでのメールトラブルシューティング](Troubleshoot email on a new Discourse install)を参照してください。おそらく、以下のようなコマンドを実行したいのだと思います。

 rake emails:test[user@domain]
「いいね!」 3

ありがとうございます。参考になりました。結果は以下の通りです。\n\n```bash
Testing sending to user@domain using outbound-relays.techservices.illinois.edu:25, username: with plain auth.
======================================== ERROR ========================================
UNEXPECTED ERROR

SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

====================================== SOLUTION =======================================
This is not a common error. No recommended solution exists!

Please report the exact error message above to https://meta.discourse.org/
(And a solution, if you find one!)

コンテナを再構築して、コンテナと`app.yml`が同期していることを確認します。しかし、全体的に、`app.yml`設定ファイルにユーザー名もパスワードも指定されていないのに、プレーン認証を使用していると表示される理由が少しわかりません。\n\nこれをバグとして再分類する価値はありますか?当初は躊躇していました。メールであり、この問題が発生する可能性はたくさんあり、その多くは私のせい、または外部の変更の組み合わせである可能性があります。しかし、私の知る限り、これは数年間機能していた設定が、`discourse_docker`の最新バージョンへのアップグレードで突然停止したことを表しています。設定ファイルの処理方法が最近変更された可能性はありますか?\n\nエラーメッセージについてですが、そのマシン用の証明書を取得でき、確かに証明書には別のホスト名(同じマシンの別のCNAME)が記載されています。しかし、証明書自体は数年前のもので、約1年前に期限切れましたが、最近になってこのエラーが発生し始めました。そのため、問題の原因は証明書の変更ではないと考えています。
「いいね!」 2

そのホストに接続して STARTTLS をテストすると、ホスト名と一致しない証明書が返されます。

証明書チェーン
 0 s:/C=US/ST=California/L=Sunnyvale/O=Proofpoint, Inc./OU=ESP/CN=*.pphosted.com
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=Thawte RSA CA 2018
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=Thawte RSA CA 2018
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA

まだ期限切れではありません。

notBefore=Jun 12 00:00:00 2020 GMT
notAfter=Sep 14 12:00:00 2022 GMT

フォワードおよびリバースルックアップを行うと、メールサーバーは実際には mx0a-00007101.pphosted.com および mx0b-00007101.pphosted.com と呼ばれていることがわかります。

outbound-relays.techservices.illinois.edu. 22 IN A 148.163.139.28
outbound-relays.techservices.illinois.edu. 22 IN A 148.163.135.28

28.139.163.148.in-addr.arpa name = mx0b-00007101.pphosted.com.
28.135.163.148.in-addr.arpa name = mx0a-00007101.pphosted.com.

接続するホスト名を .edu 名の代わりに、これらのいずれかに変更してみてください。証明書の変更は必要ないかもしれませんが、ホスト名またはコードの変更が必要な場合があります。しかし、エラーは正しいです。実際にホスト名の証明書の不一致があります。

「いいね!」 4

@RGJさん、ありがとうございます!試してみます。

ただ、これらの名前は将来変更される可能性があり、学内でのこの目的のために提供されているホスト名とも一致しないため、使用するには少し不安があります。app.ymlの設定やその他の方法で、このエラーを無効にする方法はありますか?

「いいね!」 1

私のやり方は、まず動くようにして、それからどうすればもっと良くなるかを見つけることでした。

DISCOURSE_SMTP_OPENSSL_VERIFY_MODEfalse に設定できるはずですが、すでに試したとのことでした。

「いいね!」 5

はい、もちろんです!理にかなっています。

その値を none に設定しようとしたことはありますが、false には設定していませんでした。false で試してみます。

「いいね!」 2

わかりました、false が機能しないことを確認しました。もう一度 none を試してみます。

「いいね!」 1

none も機能しないことを確認することもできます。

これは妥当な動作かどうか、少し途方に暮れています。DISCOURSE_SMTP_ENABLE_START_TLSfalse に設定されており、少なくとも私のようなメール専門家ではない者にとっては、証明書がこの障害に関与していることが混乱を招く原因となるでしょう。マシンに証明書がまったくなかった場合、この同じ問題が発生するでしょうか?(明らかにテストできません。)そうでない場合、さらに奇妙に思えます。

とにかく、今のところ一時的な修正で対応しますが、この件については何か奇妙に感じています。

「いいね!」 1

確かに。メールサーバーがstarttlsを要求する場合、starttls設定をオーバーライドしますが、DISCOURSE_SMTP_OPENSSL_VERIFY_MODEはそれでもエラーを防ぐことができるはずだと想像できます。

誰かこれを再現できますか?

「いいね!」 2

@Geoffrey_Challen さん、どうやって解決しましたか?

本日、フォーラムを 2.9.0.beta4 (c99a6b10fb) にアップデートしたところ、同じエラーが発生しました。Discourse がメールを送信できません。
SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

VPS やメールの設定は何も変更していません!

私の app.yml です。

  DISCOURSE_SMTP_ADDRESS: smtp.mydomain.info
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: info@mydomain.info
  DISCOURSE_SMTP_PASSWORD: "mypassword"
  DISCOURSE_SMTP_ENABLE_START_TLS: false           # (optional, default true)
  DISCOURSE_SMTP_DOMAIN: mydomain.info             # (required by some providers)
  #DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.example.com    # (address to send notifications from)

試しましたが、何も変わりません…

メールが送信できず、TLS も使用できないのですが、どうすればよいでしょうか?

「いいね!」 2

このコマンドを実行して、証明書がどのホスト名用かを確認してください。

openssl s_client -connect  smtp.mydomain.info:25 -starttls smtp -showcerts 2>&1|grep "depth=0"

もちろん、smtp.mydomain.info はご自身の SMTP サーバーのアドレスに置き換えてください。

次に、そのホスト名を使用して SMTP サーバーに到達できるかどうかを確認してください。

「いいね!」 3

ご協力ありがとうございます @RGJ

ホスト名は CN = *.aruba.it なので、mydomain.info とは異なります。はい、ホスト名と telnet を使用して SMTP サーバーに接続できます。

./launcher rebuild app の前はすべて完璧に機能していました。

しかし… DISCOURSE_SMTP_ENABLE_START_TLS: false ですが、なぜ証明書を探し続けるのでしょうか?

「いいね!」 1

証明書と一致する名前を使用してホストにアクセスできます。サーバー管理者に、証明書に希望するホスト名を追加するように依頼できます。

それは良い質問ですが、上記のアドバイスに従うことで、その答えを無効にすることができます。そうだと思います。

別の質問ですが、メール管理者はなぜあなたのためにそれを壊したのかと思いますか?

おそらくその設定は以前は機能していましたが、今は機能しません。そのバグを突き止める方が簡単か、ホスト名を変更して問題が解決するかどうかを確認する方が簡単かは不明です。

「いいね!」 1

誰も変更を加えていません。私は、このプラグインをインストールするために ./launcher rebuild を実行しただけです。

では、VPSのホスト名を .aruba.it で終わるものに変更すべきでしょうか?

「いいね!」 1

そのように聞こえます。

問題を引き起こしたリグレッションの可能性がありますが、ホスト名を変更することで、当面の懸念を解決できると思います。

「いいね!」 2