O fato é que o Let’s Encrypt conquistou o mercado revolucionando o acesso aos certificados gratuitos. A EFF – Electronic Frontier Foundation fez um trabalho sensacional democratizando o acesso e permitindo que a internet fosse um lugar mais seguro de forma acessível para todos. Portanto fica o registro e meus mais honestos agradecimentos.
Mas diversidade é bom e todos gostam.
A Let’s Encrypt trabalha com dois servidores separados: um para testes e um de produção e não é incomum esquecermos disso. O servidor de produção tem um limite de tentativas que quando atingido te bloqueia por uma uma semana.
O objetivo é evitar sobrecarregar o servidor de produção e eles estão certíssimos, mas na “hora da agonia” isso pode ser um desastre. A urgência em gerar ou renovar um certificado te leva a fazer 10 tentativas e o Let’s Encrypt bloqueia seu acesso. Como ficar uma semana sem certificado?
A necessidade faz o homem é um provérbio antigo e um dos mais reais também. Eu cai nessa pegadinha e antes de ser consumido pelo desespero, me lembrei da dica do amigo Fábio Schmidt que tinha me falado sobre o acme.sh e o ZeroSSL.
A busca foi rápida e achei que o acme.sh já tem suporte ao Let’s Encrypt e seria um substituto muito interessante ao certbot, mas só isso não me ajudaria. O problema não era o certbot, mas o fato do servidor de produção do Let’s Encrypt ter me bloqueado.
O que eu queria era gerar o certificado da ZeroSSL e instalar ele no Zimbra.
Não achei nenhum material nas buscas, então aceitei o desafio e meti a mão no script =)
O maior desafio foi achar o CA Root certo e a ordem de concatenação das chaves para que o Zimbra aceitasse o certificado.
O certificado gratuito da ZeroSSL também tem duração de 90 dias igual ao Let’s Encrypt.
Segue abaixo o caminho das pedras. Espero que gostem.
A partir de agora, podemos escolher usar Let’s Encrypt ou ZeroSSL para nossos certificados. Ter opção de escolha é tudo de bom. Segue o tutorial.
Instalando o acme.sh
A instalação do acme.sh é super simples e tem uma única dependência: socat. Então instale ele antes. Os comandos abaixo são para Ubuntu.
apt -y install socat
cd /root
wget -O - https://get.acme.sh | sh
cd /root/.acme.sh
Gerando o certificado
O acme.sh funciona na mesma lógica do certbot, subindo um servidor web local com as portas 80 e 443, portanto o Zimbra tem que estar parado para o acme.sh funcionar em modo standalone. Se quiser usar outros meios como validação por DNS consulte o github do projeto.
Será necessário, também, registrar um e-mail que ficará vinculado ao certificado gerado.
Vamos aos comandos:
su - zimbra -c "zmcontrol stop"
./acme.sh --register-account -m [email protected]
./acme.sh --issue --standalone --keylength 2048 -d mail.exemplo.com.br -d webmail.exemplo.com.br
Perceba que da mesma forma que fazemos no certbot a sequência de domínios é passada usando um “-d” para cada domínio.
Quando o acme.sh gerar o certificado, os arquivos estarão em um diretório com o nome do primeiro domínio da lista, que no exemplo acima é mail.exemplo.com.br
Copiando os arquivos necessários para /tmp
O usuário zimbra não vai conseguir ler os arquivos do /root, portanto vamos fazer uma cópia para /tmp, assim:
mkdir -p /tmp/zero.exemplo.com.br
cd mail.exemplo.com.br
cp * /tmp/zero.exemplo.com.br
cd /tmp/zero.exemplo.com.br
Baixando e concatenando o CA Root
Em seguida vamos baixar o CA Root correspondente ao ZeroSSL e concatenar a cadeia de certificados da forma correta para que o gerenciador de certificados do Zimbra funcione como esperado.
Esta parte foi a mais desafiadora, porque a ZeroSSL não compartilha essa informação. Por isso mesmo eu copiei o CA root para meu blog e vamos fazer o download de lá. Seguem os comandos:
cd /tmp/zero.exemplo.com.br
wget --no-check-certificate http://www.anahuac.eu/USERTrustRSACertificationAuthority.crt
cat USERTrustRSACertificationAuthority.crt fullchain.cer > zimbra_ca.pem
Corrigindo permissões
Todos os arquivos que estão no /tmp/zero.exemplo.com.br tem que estar com permissões para o usuário zimbra.
chown zimbra: /tmp/zero.exemplo.com.br -R
Testando o certificado
Certificado gerado, CA Root no lugar, permissões corrigidas…. hora de testar se esta tudo perfeito. Execute:
su - zimbra -c"cd /tmp/zero.exemplo.com.br ; /opt/zimbra/bin/zmcertmgr verifycrt comm mail.exemplo.com.br.key mail.exemplo.com.br.cer zimbra_ca.pem"
Se tudo deu certo, podemos seguir adiante e instalar o certificado da ZeroSSL
Instalando o certificado
Últimos passos:
cp mail.exemplo.com.br.key /opt/zimbra/ssl/zimbra/commercial/commercial.key -rf
chown zimbra: /opt/zimbra/ssl/zimbra/commercial/commercial.key
su - zimbra -c"cd /tmp/zero.exemplo.com.br ; /opt/zimbra/bin/zmcertmgr deploycrt comm mail.exemplo.com.br.cer zimbra_ca.pem"
Finalmente inicie o Zimbra:
su - zimbra -c "zmcontrol start"
Script para agilizar
Quero compartilhar com vocês o script que fiz para realizar as tarefas acima e mais: ele também gera e instala certificados com Let’s Encrypt.
Então esse é um script multi função que usa acme.sh em vez de certbot para instalar certificados gerados pelo Let’s Encrypt ou ZeroSSL a sua escolha. Basta configurar as variáveis no inicio do script.
#! /bin/bash
domain="exemplo.com.br"
certs_dom="mail.exemplo.com.br"
dom_list="-d mail.exemplo.com.br -d webmail.exemplo.com.br"
cert_path="/root/.acme.sh/mail.exemplo.com.br"
zerossl="yes"
letsencrypt="no"
if [ "$domain" = "" ] ; then
echo "Defina as variáveis no início do script"
exit
fi
echo -n "Tem que parar o Zimbra: [Y/n] "
read rest
if [ "$rest" = "" ] || [ "$rest" = "Y" ] ; then
su - zimbra -c"zmcontrol stop"
fi
apt -y install socat
cd /root
wget -O - https://get.acme.sh | sh
cd /root/.acme.sh
rm $cert_path -rf
if [ "$zerossl" = "yes" ] && [ "$letsencrypt" = "yes" ] ; then
echo "Pick one: zerossl or letsencrypt!"
exit
fi
if [ "$zerossl" = "no" ] && [ "$letsencrypt" = "no" ] ; then
echo "Pick one: zerossl or letsencrypt!"
exit
fi
if [ "$zerossl" = "yes" ] ; then
./acme.sh --register-account -m zerossl@$domain
./acme.sh --issue --standalone --keylength 2048 $dom_list
if [ "$?" != "0" ] ; then
echo ""
echo "Deu erro ao gerar o certificado para o dominio $domain"
exit 1
fi
fi
if [ "$letsencrypt" = "yes" ] ; then
# Testa a geração do certificado
./acme.sh --set-default-ca --server letsencrypt_test
./acme.sh --issue --standalone --preferred-chain "ISRG Root X1" --keylength 2048 $dom_list
if [ "$?" != "0" ] ; then
echo ""
echo "Erro na no certificado para o dominio $domain"
echo ""
exit 1
else
rm $cert_path -rf
fi
# Gera o certificado
./acme.sh --set-default-ca --server letsencrypt
./acme.sh --issue --standalone --preferred-chain "ISRG Root X1" --keylength 2048 $dom_list
# Registrar se deu erro e abortar esse procedimento
if [ "$?" != "0" ] ; then
echo ""
echo "Deu erro ao gerar o certificado para o dominio $domain"
exit 1
fi
fi
# Entrar no dir certo, que é o primeiro dominio
cd $cert_path
if [ "$letsencrypt" = "yes" ] ; then
# Copiando para permitir acesso ao usuário zimbra
mkdir -p /tmp/lets.$domain
rm /tmp/lets.$domain/* -rf
cp * /tmp/lets.$domain
cd /tmp/lets.$domain
tmp_path="lets"
wget --no-check-certificate -O ISRG-X1.pem https://letsencrypt.org/certs/isrgrootx1.pem.txt
cat fullchain.cer ISRG-X1.pem > zimbra_ca.pem
fi
if [ "$zerossl" = "yes" ] ; then
# Copiando para permitir acesso ao usuário zimbra
mkdir -p /tmp/zero.$domain
rm /tmp/zero.$domain/* -rf
cp * /tmp/zero.$domain
cd /tmp/zero.$domain
tmp_path="zero"
wget --no-check-certificate http://www.tbs-x509.com/USERTrustRSACertificationAuthority.crt
cat USERTrustRSACertificationAuthority.crt fullchain.cer > zimbra_ca.pem
fi
chown zimbra: /tmp/$tmp_path.$domain -R
su - zimbra -c"cd /tmp/$tmp_path.$domain ; /opt/zimbra/bin/zmcertmgr verifycrt comm $certs_dom.key $certs_dom.cer zimbra_ca.pem"
if [ "$?" != "0" ] ; then
echo ""
echo "Deu erro aotestr o certificado para o dominio $domain"
exit 1
fi
cd /tmp/$tmp_path.$domain
cp $certs_dom.key /opt/zimbra/ssl/zimbra/commercial/commercial.key -rf
chown zimbra: /opt/zimbra/ssl/zimbra/commercial/commercial.key
su - zimbra -c"cd /tmp/$tmp_path.$domain ; /opt/zimbra/bin/zmcertmgr deploycrt comm $certs_dom.cer zimbra_ca.pem"
echo -n "Tem que iniciar o Zimbra: [Y/n] "
read rest
if [ "$rest" = "" ] || [ "$rest" = "Y" ] ; then
su - zimbra -c"zmcontrol start"
fi