Incompatibilidade do certificado do hostname do e-mail causando sobrecarga na fila do sidekiq, instabilidade severa do site

Há muitos anos que hospedo o Discourse em auto-hospedagem, e tive várias instâncias configuradas e funcionando bem em uma máquina bastante robusta.

Hoje notei que um dos meus fóruns parou de funcionar. O culpado inicial parecia ser a falta de espaço em disco, que eu corrigi. Em seguida, reiniciei a instância do Discourse.

No entanto, ele continuou a cair regularmente desde então. Cada vez que eu o reinicio, vejo imediatamente o sidekiq enlouquecer e um grande número de trabalhos de e-mail falhando, o que também está fazendo com que o redis armazene uma quantidade massiva de estado, o que eu acho que foi a causa real do problema de espaço em disco. (Estou prestes a fazer um flush na próxima vez que conseguir colocar a máquina no ar, pois se não o fizer, ficarei rapidamente sem espaço nesta máquina e nem conseguirei iniciar o Discourse para fazer o flush. Mas o flush não parece reduzir muito o uso de disco do redis.)

A mensagem de erro indica algo sobre uma incompatibilidade de nome de certificado, o que acho um pouco surpreendente, já que o servidor de e-mail que estou usando é interno e não requer TLS ou autenticação. Consegui verificar em uma das minhas outras instâncias (usando a mesma configuração de e-mail) que o e-mail parou de funcionar. Tudo o que consigo ver nos principais logs de produção é um erro 422, mas quando envio algo como uma redefinição de senha, vejo um erro semelhante nos logs do sidekiq:

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

Consegui verificar que consigo enviar e-mails pela linha de comando, então isso não parece ser um problema com o próprio servidor de e-mail, apenas algo quebrado na configuração do Discourse.

Aqui está a configuração de e-mail original que estava funcionando até recentemente:

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

Novamente, este servidor de e-mail é interno e não requer nome de usuário ou senha, e essas configurações estavam funcionando até recentemente. Tenho experimentado com DISCOURSE_SMTP_OPENSSL_VERIFY_MODE, mas não consigo dizer se ele ainda é suportado. De qualquer forma, não parece ajudar. Notei algumas novas configurações de e-mail que foram adicionadas desde que configurei esses fóruns, mas elas não parecem necessárias dada a configuração deste servidor de e-mail.

Qualquer ajuda seria apreciada! A esta altura, estou honestamente tendo dificuldade em ter certeza do que está errado ou em iterar, já que reconstruir o contêiner leva tempo e a mensagem de erro nos logs de produção tem apenas o erro 422 e não consigo descobrir onde procurar a causa raiz real. (Deve estar em algum lugar, certo? Tenho certeza de que estou apenas perdendo.)

1 curtida

Como uma atualização, seguindo o conselho em outro tópico, este comando envia e-mail com sucesso de dentro do contêiner Docker:

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

O que corresponde à configuração de e-mail que eu estava usando quando este problema começou. Observe que também realizei uma atualização para o Discourse mais recente por meio de um pull (obrigatório) pela linha de comando na sexta-feira, o que me faz pensar se um commit recente trouxe este problema.

2 curtidas

Quando foi a última vez que você reconstruiu o contêiner?

Além disso, você limpou a fila do Redis?

2 curtidas

Sexta-feira de manhã, acredito. Uma atualização normal pela interface do usuário acionou a necessidade de uma reconstrução do aplicativo launcher. Quando examinei os logs do sidekiq mais tarde, pareceu que o backlog começou na época em que o contêiner foi reconstruído, mas levou cerca de 24 horas para os logs do Redis consumirem todo o armazenamento disponível no host e realmente causarem inatividade. No entanto, o fórum provavelmente ficou lento antes disso, dado que o sidekiq estava tentando desesperadamente reenviar um número crescente de trabalhos de e-mail com falha com 100% de uso da CPU.

Sim.

No entanto, me preocupa que isso não tenha reduzido o uso de disco do Redis. Tenho uma pasta redis_data que atualmente tem 29G de tamanho, mesmo após a limpeza. Talvez o Redis seja como o MongoDB, em que pode ser difícil fazê-lo retornar as alocações de disco? Dado que isso é 1/3 do disco disponível na máquina, isso se tornará um problema, mas vou adiar isso por enquanto em favor de apenas fazer o e-mail funcionar novamente.

1 curtida

Como uma nota de depuração: existe uma maneira de enviar um e-mail de teste da linha de comando dentro do contêiner, usando o mesmo fluxo de código que seria usado pelo Discourse? (Ou seja, não da linha de comando usando outra ferramenta, o que já verifiquei que funciona.) Isso seria útil para depuração, pois atualmente enviar um e-mail de teste requer mexer na interface do usuário da web e, em seguida, vasculhar os logs para descobrir o que deu errado. (E até agora só encontrei os erros 422, e nada mais útil, exceto nos logs do sidekiq que não são criados ao usar o fluxo de e-mail de teste.) Ou talvez a interface de e-mail de teste possa exibir mais informações de depuração?

No geral, suspeito que a maioria das pessoas configura o Discourse e não chega a este ponto sem que o e-mail funcione, pois ele é necessário para enviar convites iniciais e assim por diante. Mas estou achando a depurabilidade limitada no caso em que o e-mail estava funcionando e de repente parou. (Além disso, a lógica de retentativa pode precisar de alguns ajustes, pois parece muito rápida para retentar neste caso. Um erro de certificado provavelmente não será corrigido alguns segundos após a tentativa inicial…)

1 curtida

Talvez veja E-mail de solução de problemas em uma nova instalação do Discourse. Eu acho que você quer

rake emails:test[user@domain]
3 curtidas

Obrigado! Isso é útil. Aqui está o resultado:

Testing sending to user@domain using outbound-relays.techservices.illinois.edu:25, username: with plain auth.
======================================== ERRO ========================================
                                    ERRO INESPERADO
                                    
SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

====================================== SOLUÇÃO =======================================
Este não é um erro comum. Nenhuma solução recomendada existe!

Por favor, relate a mensagem de erro exata acima para https://meta.discourse.org/
(E uma solução, se você encontrar uma!)
=======================================================================================

Vou reconstruir o contêiner agora para garantir que ele e o app.yml estejam sincronizados. Mas, no geral, estou um pouco confuso por que ele diz que está usando autenticação simples, já que nenhum nome de usuário ou senha é fornecido no arquivo de configuração app.yml.

Vale a pena reclassificar isso como um bug? Hesitei inicialmente, pois é e-mail e há muitas maneiras pelas quais isso pode estar se comportando mal, muitas das quais seriam alguma combinação de minha culpa / alterações externas. Mas, tanto quanto posso dizer, isso representa uma configuração que funcionou por vários anos e de repente parou em uma atualização para a edição mais recente do discourse_docker. É possível que algo sobre como os arquivos de configuração estão sendo processados tenha mudado recentemente?

Em relação à mensagem de erro em si, consegui obter um certificado para essa máquina e, de fato, o certificado lista outro nome de host (um CNAME diferente para a mesma máquina). No entanto, o certificado em si é de vários anos atrás e também expirou há cerca de um ano, mas começou a gerar esse erro recentemente. Isso me faz pensar que não foi uma alteração no certificado que está causando o problema.

2 curtidas

Ao conectar-me a esse host e testar o STARTTLS, recebo um certificado que não corresponde ao nome do host:

Certificate chain
 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

e ele ainda não expirou:

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

Uma consulta direta e reversa mostra que os servidores de e-mail são, na verdade, chamados mx0a-00007101.pphosted.com e 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.

Tente alterar o nome do host ao qual você se conecta para um desses em vez do nome .edu. Não precisa ser uma alteração no certificado, pode ter sido uma alteração no nome do host ou no código. Mas o erro está correto: há de fato uma incompatibilidade de certificado de nome de host.

4 curtidas

Obrigado @RGJ! Vou tentar isso.

No entanto, estou um pouco nervoso em usar esses nomes, dado que eles podem estar sujeitos a alterações no futuro e não correspondem ao nome do host que é fornecido para uso no campus para esse fim. Existe alguma maneira de desativar esse erro via configurações de app.yml ou de alguma outra forma?

1 curtida

Minha abordagem foi fazer as coisas voltarem a funcionar primeiro, depois descobrir como melhorá-las.

Você deve conseguir definir DISCOURSE_SMTP_OPENSSL_VERIFY_MODE como false, mas você disse que já tentou isso.

5 curtidas

Sim, com certeza! Faz sentido.

Acho que tentei definir esse valor como none, mas não como false. Vou tentar false.

2 curtidas

OK, posso confirmar que false não funciona. Tentarei none novamente.

1 curtida

Também posso verificar que none não funciona.

Acho que estou um pouco confuso aqui sobre se este é um comportamento razoável. DISCOURSE_SMTP_ENABLE_START_TLS está definido como false, o que, pelo menos para os não especialistas em e-mail como eu, causaria confusão o fato de um certificado desempenhar um papel nessa falha. Se a máquina não tivesse um certificado, ocorreria o mesmo problema? (Obviamente, não posso testar isso.) Se não, parece ainda mais estranho.

De qualquer forma, vou com a correção temporária por enquanto, mas algo sobre isso me parece estranho.

1 curtida

Certamente. Posso imaginar que se um servidor de e-mail exigir starttls, ele substituirá a configuração starttls, mas DISCOURSE_SMTP_OPENSSL_VERIFY_MODE ainda deve ser capaz de evitar um erro.

Alguém consegue reproduzir isso?

2 curtidas

@Geoffrey_Challen como você corrigiu?

Hoje atualizei meu fórum para 2.9.0.beta4 (c99a6b10fb) e agora tenho o mesmo erro, o discourse não consegue enviar e-mails:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (Hostname mismatch)

Eu não mudei a configuração do VPS e do e-mail!

Meu 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)

Tentei e nada muda…

Por favor, agora não consigo enviar e-mails e não posso usar TLS, o que posso fazer?

2 curtidas

Execute este comando e veja para qual nome de host o certificado é válido

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

Substituindo smtp.mydomain.info pelo endereço do seu servidor SMTP, é claro.

Em seguida, tente ver se você consegue alcançar o servidor SMTP usando esse nome de host.

3 curtidas

Obrigado pela sua ajuda @RGJ

o nome do host é CN = *.aruba.it, então é diferente do meu mydomain.info e sim, consigo acessar o servidor SMTP usando o nome do host e o telnet.

Tudo funcionou perfeitamente antes de ./launcher rebuild app

Mas… eu tenho DISCOURSE_SMTP_ENABLE_START_TLS: false, por que ele continua procurando o certificado?

1 curtida

Você pode acessar o host usando um nome que corresponda ao certificado. Você pode pedir ao administrador do servidor para adicionar o nome do host que você deseja ao certificado.

Essa é uma boa pergunta, mas você pode tornar a resposta irrelevante seguindo o conselho acima, ou assim eu penso.

Outra pergunta, eu acho, é por que o administrador de e-mail quebrou isso para você?

Talvez essa configuração tenha funcionado antes e agora não funcione mais. Se é mais fácil rastrear esse bug ou alterar o nome do host e ver se isso resolve seu problema, não está claro.

1 curtida

Ninguém fez nenhuma alteração, tenho certeza, eu apenas executei ./launcher rebuild para instalar este plugin.

Então, devo mudar o nome do host do VPS para algo que termine com .aruba.it?

1 curtida

É o que parece.

É possível que haja uma regressão que causou o problema, mas acho que você pode resolver seu problema imediato mudando o nome do host.

2 curtidas