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

有没有办法将 Discourse “降级”到旧的可用版本(例如 2.8.0 stable 或 2.9.0 beta3),直到这个问题得到解决?

1 个赞

我决定再花半小时来深入研究一下,我认为我已经找到了原因。

这似乎与迁移到 Rails 7 有关,Rails 7 将 net-smtp 从 0.1.0 更新到了 0.3.1,这改变了默认设置。

smtp gem 调用 net-smtp 的方式并没有禁用 enable_starttls_autoopenssl_verify_mode,它只是在启用时才启用它们。

相关:SMTP: allow disabling starttls_auto since it's now true by default in Ruby 3 by jeremy · Pull Request #1435 · mikel/mail · GitHub

10 个赞

干得好,Richard!这本来需要我两个小时,甚至更长的时间。对我来说,屈服于处理新的默认设置更容易。

啊哈。所以我的想法有点对,只是修复它可能并不太难。

4 个赞

干得好,@RGJ

在我们期待修复的同时,顺便说一句,如果这个问题不会导致我遇到的连锁问题,那将是很好的,这些问题几乎让我的论坛彻底瘫痪。具体来说:

  • 电子邮件失败似乎会非常快速地重试,这会导致 sidekiq 队列的规模爆炸,并且这些任务导致 CPU 使用率达到 ~100%。
  • 此外,某些东西(崩溃或重启)导致 Redis 写入巨大的临时文件,我假设这些文件包含 sidekiq 队列的状态。虽然可以安全地删除它们,但它们很快就填满了磁盘,这导致了更多的崩溃,等等。我有一些其他的磁盘空间可以释放,以便重新启动论坛并弄清楚发生了什么,但这可能不适用于所有人。(而且,在这种情况下,也很难确认 Redis 临时文件实际上可以安全删除。)

我猜最简单的解决方案是减慢失败电子邮件作业的重试速度——或者至少是那些没有密码重置等时效性约束的作业。鉴于电子邮件问题不太可能很快解决,而且大多数/所有邮件发送者在收到消息后都会进行自己的重试,这似乎是合适的。

8 个赞

在我的案例中,升级后遇到失败时,它正在使用 TLS 与第三方服务器通信,并且证书上的名称与 smtp 服务器名称匹配。但我只遇到了一次失败。为了避免进一步的问题,我还没有重新启动或升级。一旦补丁发布,我会尝试更新并看看效果如何。

2 个赞

我将首先创建一个关于 Bug主题,但由于这在技术上是上游 gem 的一个问题,我不确定它会有多大的优先级。

3 个赞

+1 :worried: 令人沮丧的错误

1 个赞

不能回滚这个 gem 吗?如果它没有得到关注,我会感到惊讶,因为这是“核心”功能,即发送电子邮件的能力,而且对某些人来说,它还导致了临时文件和 CPU 耗尽服务器的故障。论坛的核心稳定性在这里受到干扰。

2 个赞

请不要忘记,通过正确配置邮件服务器也可以轻松解决此问题。

1 个赞

据我所知,我的服务器配置正确。证书名称与 smtp 主机名匹配,端口 587 上有 STARTTLS。我想知道为什么我会遇到这个问题?

感谢您开启新工单。鉴于您的理解,您能否阐明您在 YML 文件中指出的两个变量的组合——它们应该如何在不同场景下使用?

DISCOURSE_SMTP_ENABLE_START_TLS: true
DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none

例如,出于安全原因,我只在端口 587 上使用 STARTTLS,而不使用其他 SMTP 端口。是否应该在 YML 文件中同时指定这两个变量,还是只指定一个?

2 个赞

这取决于。
如果您的 SMTP 服务器配置正确,则您不需要其中任何一个。

但目前的问题是它们根本不起作用。

给我发一封私人消息,告诉我您的 SMTP 服务器名称,我会看看能否找出它为什么对您不起作用。

2 个赞

我有一个本地 SMTP 服务器,不支持 TLS/SSL,并且在使用 StartTls=false 时不起作用 :frowning:

1 个赞

说得有理,但并非总是 我们的 邮件服务器。我正在使用一个由其他小组维护的内部邮件服务器,因此无法控制证书问题或邮件服务器配置。

话虽如此,对于其他遇到此问题的人来说,一种选择可能是设置您自己的本地邮件服务器,然后让它转发邮件。这样,您就可以控制 Discourse 连接到的邮件服务器,并且您的本地邮件服务器可以配置为处理您可能遇到的任何上游问题。我以前这样做过,但后来将其删除,因为让 Discourse 直接连接到上游邮件服务器更简单。(哎呀。)

1 个赞

这就是为什么标准安装推荐使用第三方邮件提供商,而不是尝试使用现有或自托管的解决方案。

邮件之所以困难,原因有很多,仅仅因为某项功能今天能正常工作,并不意味着它的配置是正确的,只表示错误的配置没有影响到其原始目的。

1 个赞

我选择 Discourse 的原因在于它声称易于安装和维护,适合小型自托管部署。

1 个赞

如果您遵循建议,确实是这样。

如果您选择走另一条路,则无法真正做出任何保证。

1 个赞

所以总而言之,您的意思是使用 discourse 不再可能在没有 TLS、SSL 或 StartTLS 的情况下使用 SMTP 服务器了?

1 个赞

我不认为有人在建议这个。这只与问题的发生方式以及找到根本原因所花费的时间有关。

我们之所以只在这里看到少数案例,是因为安装了更新的 gem 并且没有通过某种形式的安全传输来传递邮件的安装数量相对较少。

Richard 已经在一个关于这个 bug 的主题中开始了讨论:

对于任何需要更快解决此问题的人,他们也可以启用邮件服务器上的 TLS,或者暂时切换到提供安全传输的邮件提供商。

1 个赞

我从一开始就启用了 TLS,并使用了有效的证书和匹配的主机名,然后在 BETA 4 (461936f211) 升级后遇到了问题,并在下面的主题中发布了日志。另一位用户也遇到了问题,据他说,他的证书也是正常的:

1 个赞

听起来是这样。这个帖子里的有些评论简直令人恼火。

我自行托管 Docker-Discourse,并使用我的 Docker 主机作为邮件服务器。自从六年前开始,我就一直让 Discourse 使用 25 端口,通过内部 Docker 接口发送邮件,而无需 TLS。这是一个完全合理且完全安全的配置。事务完全是我自己主机内部的。请参阅帖子前面部分了解我的旧配置。

对我来说,解决方法是执行以下操作:

将主机的内部 Docker 接口 IP 地址添加为我域的 DNS 区域文件中的有效主机。即:

discourse-mail.jag-lovers.com A 172.17.0.1

请注意:由于我使用通配符证书(CN = *.jag-lovers.com),我可以随意在 jag-lovers.com 域中设置任何主机名。如果您没有通配符证书,请确保使用证书上 CN 或 SAN 有效的主机名。

另请注意:上面使用的 IP 地址是我的主机在 Docker 接口上用于与 Discourse-Docker 容器通信的内部 IP 地址。这是一个私有的、不可路由的 IP 地址。

接下来,更改 Discourse app.yml 配置,使其连接到我刚创建的主机名,使用 TLS,连接到 587 端口,并使用 SASL 为每次邮件事务登录主机(否则您会收到中继被拒绝的错误消息)。

  DISCOURSE_SMTP_ADDRESS: discourse-mail.jag-lovers.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: REDACTED
  DISCOURSE_SMTP_PASSWORD: "REDACTED"
  DISCOURSE_SMTP_ENABLE_START_TLS: true          # (optional, default true)
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_DOMAIN: jag-lovers.com

接下来,重建 Discourse。这为我解决了问题。

2 个赞