邮件主机名证书不匹配导致 sidekiq 队列过载,严重网站不稳定

我多年来一直在自行托管 Discourse,并且在几台性能不错的机器上成功配置并运行了多个实例。

今天我注意到我的一个论坛无法访问。最初的原因似乎是磁盘空间不足,我已修复。然后我重新启动了 Discourse 实例。

但是,此后它一直定期出现故障。每次启动它,我都会立即看到 sidekiq 变得非常活跃,并且有大量电子邮件作业失败,这也会导致 redis 存储大量状态,我认为这实际上是磁盘空间问题的根本原因。(下次我能启动机器时,我将执行一次刷新,因为如果我不这样做,我将很快用完这台机器上的空间,甚至无法启动 Discourse 进行刷新。但刷新似乎并没有怎么减少 redis 的磁盘使用量。)

错误消息表明与证书名称不匹配有关,这让我有些惊讶,因为我使用的邮件服务器是内部的,不需要 TLS 或身份验证。我在我的另一个实例(使用相同的电子邮件配置)上能够验证电子邮件已停止工作。我在主生产日志中看到的唯一信息是 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,但我无法确定它是否仍然受支持。无论如何,它似乎没有帮助。我注意到自设置这些论坛以来添加了一些新的电子邮件设置,但考虑到此邮件服务器的配置,它们似乎是不需要的。

任何帮助都将不胜感激! at this point I’m honestly even having a hard time being sure of what is wrong or iterating, since rebuilding the container takes a while and the error message in the production logs only has the 422 error and I can’t figure out where to look for the actual root cause. (It must be somewhere, right? I’m sure I’m just missing it.)

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 日志时,发现积压似乎是在容器重建时开始的,但直到大约 24 小时后,Redis 日志才耗尽主机上的所有可用存储并导致停机。但是,考虑到 sidekiq 以 100% 的 CPU 使用率拼命尝试重新发送越来越多的失败电子邮件作业,论坛在此之前可能已经变慢了。

是的。

然而,令我担心的是,这似乎并没有减少 Redis 的磁盘使用量。我有一个 redis_data 文件夹,目前大小为 29G,即使在刷新之后也是如此。也许 Redis 就像 MongoDB 一样,很难让它归还磁盘分配?考虑到这占用了机器上可用磁盘的 1/3,这会成为一个问题,但我现在将暂时搁置这个问题,以便让电子邮件再次正常工作。

1 个赞

作为调试说明:是否有一种方法可以在容器内的命令行中发送测试电子邮件,使用与 Discourse 相同的代码流?(也就是说,不是使用另一个工具从命令行发送,我已经验证过那个可以工作。)这对于调试很有帮助,因为目前发送测试电子邮件需要摆弄 Web UI,然后深入日志中找出哪里出了问题。(到目前为止只找到 422 错误,没有更有用的信息,除了 sidekiq 日志,但使用测试电子邮件流程时不会创建这些日志。)或者也许测试电子邮件 UI 可以显示更多调试信息?

总的来说,我怀疑大多数人在电子邮件正常工作的情况下设置 Discourse,而不会遇到这一点,因为电子邮件是发送初始邀请等所必需的。但我觉得在电子邮件曾经工作过但突然停止的情况下,调试能力有限。(此外,重试逻辑可能需要一些调整,因为它在这种情况下重试似乎太快了。证书错误可能不太可能在首次尝试后几秒钟内得到修复……)

1 个赞

也许可以看看 新 Discourse 安装的电子邮件故障排除。我认为你想要
rake emails:test[user@domain]

3 个赞

谢谢!这很有帮助。这是结果:

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 配置文件中没有提供用户名或密码。

值得将其重新归类为错误吗?我最初犹豫不决,因为它与电子邮件有关,并且有很多方法可能出现问题,其中许多可能是我的错误/外部更改的组合。但据我所知,这代表了一个已经运行了数年的配置,但在升级到最新版本的 discourse_docker 后突然停止工作。是否有可能最近处理配置文件的方式发生了变化?

关于错误消息本身——我能够为该机器拉取一个证书,事实上,证书列出了另一个主机名(同一台机器的不同 CNAME)。但是,证书本身已经有几年历史了,并且大约在一年前过期了,但最近才开始抛出这个错误。所以这让我认为问题不是证书发生了变化。

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.commx0b-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_MODE 设置为 false,但你说你已经试过了。

5 个赞

是的,完全正确!这说得通。

我想我尝试将该值设置为 none,但没有设置为 false。我会尝试 false

2 个赞

好的,可以确认 false 不起作用。我将再次尝试 none

1 个赞

也可以验证 none 无效。

我在这里有点困惑,不知道这种行为是否合理。DISCOURSE_SMTP_ENABLE_START_TLS 设置为 false,这至少对像我这样的非电子邮件专家来说,会让人觉得证书在这种失败中起作用是令人困惑的。如果机器根本没有证书,是否会发生同样的问题?(显然我无法测试。)如果不会,那就更奇怪了。

总之,我现在将采用临时修复方法,但我觉得有些地方似乎很奇怪。

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 个赞