Hoje, de repente, todas as solicitações HTTPS, que meu servidor Ubuntu 14 envia para sites com certificados SSL emitidos pela Let's Encrypt, começaram a falhar. O erro produzido pelo cURL é:
curl: (60) SSL certificate problem: certificate has expired
Quando inspeciono os certificados do site com este comando:
echo -n | openssl s_client -showcerts -connect website.com:443 -servername website.com
Vejo que toda a cadeia de certificados está atualizada.
Então, por que recebo o erro de expiração? Como corrigi-lo?
O motivo é que o certificado "DST Root CA X3" expirou ontem.
Para corrigi-lo, basta desabilitar o certificado em seu servidor. Corre:
Na primeira tela que solicita "Confiar em novos certificados de autoridades de certificação?" escolha "sim". Na próxima tela, pressione a tecla de seta para baixo no teclado até encontrar
mozilla/DST_Root_CA_X3.crt
, pressione a barra de espaço para desmarcá-la (o[*]
deve se transformar em[ ]
) e pressione Enter.Edite o arquivo /etc/ca-certificates.conf
Encontre e comente com
!
a linha como esta!mozilla/DST_Root_CA_X3.crt
Salve o arquivo e atualize os certificados com o comando
sudo update-ca-certificates
FYI em sistemas do tipo CentOS (baseados em RPM), use:
yum reinstall ca-certificates
O Android tomou uma decisão de design de ignorar a expiração dos certificados raiz (é discutível que a expiração dos certificados raiz não faz muito sentido em primeiro lugar).
"lets encrypt" é uma autoridade de certificação relativamente nova e, para dar suporte aos sistemas existentes, sua raiz foi "assinada de forma cruzada"* pelo DST. O certificado raiz DST expirou, mas devido ao comportamento do Android mencionado acima, uma assinatura cruzada ainda é útil para oferecer suporte a clientes que executam versões antigas do andriod.
Quando tal cadeia é usada em um sistema com uma lista de certificados raiz moderna, a assinatura cruzada deve ser ignorada e a raiz IRSG (permite criptografar) deve ser usada. Infelizmente o openssl 1.0.x não trata este cenário corretamente.
Esse problema pode ser contornado removendo o antigo certificado raiz de horário de verão. Quando isso for feito, a cadeia será construída corretamente na raiz do IRSG.
* Meu entendimento é que tecnicamente a "assinatura cruzada" consiste em um "certificado intermediário" com o mesmo conteúdo e chave do certificado raiz do Lets Encrypt.