Skip to main content

Gerando certificados com o LetsEncrypt

SO utilizado: Ubuntu 16.04 LTS - 18.04 LTS - 20.04 LTS - Demais Linux suportados pelo acme.sh
Fonte para HAproxy Ubuntu: https://www.digitalocean.com/community/tutorials/how-to-secure-haproxy-with-let-s-encrypt-on-ubuntu-14-04
Fonte para HAproxy CentOS: https://www.digitalocean.com/community/tutorials/how-to-secure-haproxy-with-let-s-encrypt-on-centos-7

  1. Introdução

Para a maioria dos necessidades de certificação SSL, o IFSP recomenda a geração de certificados através da utilização do CertBot\Let's Encrypt.
Através do cliente do programa Let's Encrypt, o Certbot, podemos gerar certificados de forma dinâmica para os portais que utilizam SSL de forma segura e com renovação automatizada.


  1. Instalação do software de aquisição e renovação de certificados

    1. CertBot\Let's Encrypt
  • UBUNTU

    NGINX:
    #!/bin/bash
    apt install letsencrypt && apt install python-certbot-nginx
    mkdir /var/www/html/letsencrypt
    chown www-data:www-data /var/www/html/letsencrypt
    APACHE2:
    #!/bin/bash
    apt install letsencrypt && apt install python-certbot-apache
    mkdir /var/www/html/letsencrypt
    chown www-data:www-data /var/www/html/letsencrypt
    HAPROXY:
    #!/bin/bash
    apt update && apt install certbot
    mkdir /var/www/html/letsencrypt
    chown www-data:www-data /var/www/html/letsencrypt

    CentOS

    APACHE2
    #!/bin/bash
    yum install epel-release mod_ssl && yum install certbot python-certbot-apache mod_ssl
    mkdir /var/www/html/letsencrypt
    chown www-data:www-data /var/www/html/letsencrypt
    NGINX
    #!/bin/bash
    yum install epel-release && yum install certbot-nginx
    mkdir /var/www/html/letsencrypt
    chown www-data:www-data /var/www/html/letsencrypt
    HAPROXY
    #!/bin/bash
    yum install epel-release && yum install certbot

    Alternativa universal Linux - ACME.SH

    Se você utiliza outro sistema operacional Linux ou somente não quer utilizar o certbot você pode utilizar o script acme.sh, ele tem uma lista extensa de compatibilidade de sistemas e no final irá gerar os mesmos resultados, apesar de ser menos integrado ao sistema.
    Mais detalhes no LINK

    Este sistema ainda não foi completamente validado pela reitoria em testes de longo prazo.

    curl https://get.acme.sh | sh

    O comando irá baixar e instalar o software automaticamente.

    Se estiver usando SSH faça uma nova conexão para ativar o comando

    Feito isso você pode ativar o update automático do script:

    acme.sh --upgrade --auto-upgrade

    Configuração do VHost

    CertBot\Let's Encrypt

    Devemos alterar o arquivo vhost do site alvo para que hospede o arquivo de verificação do domínio, este arquivo será utilizado para verificação da renovação no futuro pelo Let's Encrypt.

    No exemplo utilizaremos o vhost teste.ifsp.edu.br

    VHost NGINX:
    vi /etc/nginx/sites-available/teste.ifsp.edu.br

    Insira as linhas abaixo:

    location ~ /\.well-known/acme-challenge/ {
    	allow all;
        root /var/www/html/letsencrypt;
        try_files $uri =404;
        break;
    }

    O arquivo template do vhost já está atualizado com estas linhas

    VHost Apache2:
    vi /etc/apache2/conf-available/letsencrypt.conf

    Insira as linhas abaixo:

    Alias /.well-known/acme-challenge/ "/var/www/html/letsencrypt/.well-known/acme-challenge/"
    <Directory "/var/www/html/letsencrypt/">
        AllowOverride None
        Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
        Require method GET POST OPTIONS
    </Directory>

    Em seguida execute:

    a2enconf letsencrypt && systemctl reload apache2
    VHost HAproxy:

    Bom, primeiro não existe isto de VHost HAproxy, ele não é um webserver, o que faremos posteriormente é utilizar um mini servidor embutido no próprio certbot para hospedar o arquivo de verificação, chamado de "plugin standalone".

    O plugin standalone fornece um meio simples de obter o certificado SSL, ele funciona a partir de um pequeno web-server embutido que permite que o CA da Let’s Encrypt se conecte a valide a identidade do servidor antes de emitir o certificado.

    O plugin standalone funciona na porta 80, portanto o serviço do HAproxy deve estar desabilitado antes de emitir um certificado, se ele também utilizar a porta 80, a renovação do certificado não exige isto, como mostrado mais adiante.

    ACME.SH
    VHost NGINX:

    Você pode seguir os mesmos procedimentos usados no certbot.

    VHost Apache2:

    Você pode seguir os mesmos procedimentos usados no certbot.

    VHost HAproxy:

    O princípio de funcionamento é o mesmo, porém será adaptado ao funcionamento do script acme, que também possui um modo standalone com um pequeno webserver integrado.


    Geração do certificado

    Antes de gerar o certificado se certifique de que já criou as entradas relativas ao domínio no DNS.

    CertBot\Let's Encrypt

    NGINX:
    certbot --nginx -d teste.ifsp.edu.br
    APACHE2:
    certbot --apache -d teste.ifsp.edu.br

    Este comando irá gerar o certificado e irá gravar o arquivo challenge na pasta "/var/www/html/letsencrypt/.well-known/acme-challenge"

    Na primeira execução, o servidor irá fazer algumas perguntas, as respostas estão listadas a seguir

    root@DIR-SLNX-PRX-nginx-002:~# certbot --nginx -d teste.ifsp.edu.br
    
    Saving debug log to /var/log/letsencrypt/letsencrypt.log
    Plugins selected: Authenticator nginx, Installer nginx
    Enter email address (used for urgent renewal and security notices) (Enter 'c' to
    cancel): ctidocampus@ifsp.edu.br
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Please read the Terms of Service at
    https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
    agree in order to register with the ACME server at
    https://acme-v02.api.letsencrypt.org/directory
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (A)gree/(C)ancel: A
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Would you be willing to share your email address with the Electronic Frontier
    Foundation, a founding partner of the Let's Encrypt project and the non-profit
    organization that develops Certbot? We'd like to send you email about our work
    encrypting the web, EFF news, campaigns, and ways to support digital freedom.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: N
    Obtaining a new certificate
    Performing the following challenges:
    http-01 challenge for teste.ifsp.edu.br
    Waiting for verification...
    Cleaning up challenges
    Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/teste.ifsp.edu.br
    
    Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    1: No redirect - Make no further changes to the webserver configuration.
    2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
    new sites, or if you're confident your site works on HTTPS. You can undo this
    change by editing your web server's configuration.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Congratulations! You have successfully enabled https://teste.ifsp.edu.br
    
    You should test your configuration at:
    https://www.ssllabs.com/ssltest/analyze.html?d=teste.ifsp.edu.br
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    IMPORTANT NOTES:
     - Congratulations! Your certificate and chain have been saved at:
       /etc/letsencrypt/live/teste.ifsp.edu.br/fullchain.pem
       Your key file has been saved at:
       /etc/letsencrypt/live/teste.ifsp.edu.br/privkey.pem
       Your cert will expire on 2020-01-28. To obtain a new or tweaked
       version of this certificate in the future, simply run certbot again
       with the "certonly" option. To non-interactively renew *all* of
       your certificates, run "certbot renew"
     - Your account credentials have been saved in your Certbot
       configuration directory at /etc/letsencrypt. You should make a
       secure backup of this folder now. This configuration directory will
       also contain certificates and private keys obtained by Certbot so
       making regular backups of this folder is ideal.
     - If you like Certbot, please consider supporting our work by:
    
       Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
       Donating to EFF:                    https://eff.org/donate-le
    

    Feito! O Certbot automaticamente vai acessar o arquivo vhost do domínio e fará as alterações necessárias para incluir os novos certificados nele.

    Não se esqueça de verificar os arquivos vhost em busca de algo que possa ter permanecido como lixo.

    HAPROXY

    Para que o módulo standalone funcione no HAProxy durante a geração do certificado, o HAProxy deve ser desligado momentâneamente:

    systemctl stop haproxy

    Em seguida já podemos gerar o certificado

    certbot certonly --standalone --preferred-challenges http --http-01-port 80 -d teste.ifsp.edu.br

    E religar o serviço:

    systemctl start haproxy

    Em seguida configure o certificado gerado no HAproxy e aproveite para configurar o redirecionamento dos pedidos de renovação para o pequeno webserver do certbot (módulo standalone), para isto, registramos abaixo uma configuração de exemplo completa (e editada de forma genérica) utilizada em um servidor HAproxy do IFSP, mostrada abaixo.

    Esta alteração irá redirecionar o módulo standalone para a porta 54321, possibilitando assim a renovação com o serviço do HAProxy ligado.

    global
            log /dev/log    local0
            log /dev/log    local1 notice
            chroot /var/lib/haproxy
            stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
            stats timeout 30s
            user haproxy
            group haproxy
            daemon
    
            # Default SSL material locations
            ca-base /etc/ssl/certs
            crt-base /etc/ssl/private
    
            ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA
            ssl-default-bind-options no-sslv3 no-tls-tickets
    
            ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA
            ssl-default-server-options no-sslv3 no-tls-tickets
    
            # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/ssl/dhparam/dhparam
            ssl-dh-param-file /etc/ssl/dhparam/dhparam
    
    defaults
            log     global
            mode    http
            option  httplog
            option  dontlognull
            timeout connect 5s
            timeout client  720s
            timeout server  720s
            errorfile 400 /etc/haproxy/errors/400.http
            errorfile 403 /etc/haproxy/errors/403.http
            errorfile 408 /etc/haproxy/errors/408.http
            errorfile 500 /etc/haproxy/errors/500.http
            errorfile 502 /etc/haproxy/errors/502.http
            errorfile 503 /etc/haproxy/errors/503.http
            errorfile 504 /etc/haproxy/errors/504.http
    
    frontend frontend-dsi-docker-cluster
            bind :80
            bind :443 ssl crt /etc/haproxy/certs/teste.ifsp.edu.br.pem alpn h2,http/1.1
            http-request redirect scheme https unless { ssl_fc }
            # ACL para permitir o redirecionamento da renovacao para o lets encrypt
            acl letsencrypt-acl path_beg /.well-known/acme-challenge/
    
            http-response set-header Strict-Transport-Security max-age=63072000
    
            # Redireciona para o lets encrypt quando a ACL respectiva for verdadeira
            use_backend letsencrypt-backend if letsencrypt-acl
            default_backend teste-haproxy-ifsp-cluster
    
    
    backend teste-haproxy-ifsp-cluster
            balance roundrobin
            option forwardfor
            server servidor1.ifsp.edu.br  10.10.10.1:80 check
            server servidor2.ifsp.edu.br  10.10.10.2:80 check
            server servidor3.ifsp.edu.br  10.10.10.3:80 check
            http-request set-header X-Forwarded-Port %[dst_port]
            http-request add-header X-Forwarded-Proto https if { ssl_fc }
    
    # Backend criado para possibilitar a utilizacao do lets encrypt que por padrao tambem usa a porta 80
    backend letsencrypt-backend
            server letsencrypt 127.0.0.1:54321
    
    listen stats
            bind 10.10.10.4:1936
            stats enable
            stats hide-version
            stats refresh 30s
            stats show-node
            stats auth username:password
            stats uri  /stats

    Os detalhes desta configuração referentes ao "letsencrypt-backend" são importantes para a renovação automática dos certificados, tratadas em tópico posterior.

    ACME.SH

    Para gerar os certificados usando o script acme.sh, use os seguintes comandos:

    acme.sh --issue -d teste.ifsp.edu.br -w /var/www/teste

    Agora para instalar os certificados nos WebServers:

    Não utilize os certificados armazenados em "~/.acme.sh/" eles são para uso interno somente.

    NGINX

    Primeiro criamos a pasta que irá abrigar nosso certificado:

    mkdir -p /etc/nginx/acme.sh/teste.ifsp.edu.br

    Em seguida instalamos o certificado:

    acme.sh --install-cert -d teste.ifsp.edu.br \
    --cert-file      /etc/nginx/acme.sh/teste.ifsp.edu.br/cert.pem  \
    --key-file       /etc/nginx/acme.sh/teste.ifsp.edu.br/key.pem  \
    --fullchain-file /etc/nginx/acme.sh/teste.ifsp.edu.br/fullchain.pem \
    --reloadcmd     "service apache2 force-reload"

    Feito isso já pode configurar os certificados contidos na pasta criada, adicione as seguintes linhas na configuração do seu VHost:

    ssl_certificate /etc/nginx/acme.sh/teste.ifsp.edu.br/fullchain.pem;
    ssl_certificate_key /etc/nginx/acme.sh/teste.ifsp.edu.br/key.pem;
    ssl_trusted_certificate /etc/nginx/acme.sh/teste.ifsp.edu.br/cert.pem;
    APACHE2

    Primeiro criamos a pasta que irá abrigar nosso certificado:

    mkdir -p /etc/apache2/acme.sh/teste.ifsp.edu.br

    Em seguida instalamos o certificado:

    acme.sh --install-cert -d teste.ifsp.edu.br \
    --cert-file      /etc/apache2/acme.sh/teste.ifsp.edu.br/cert.pem  \
    --key-file       /etc/apache2/acme.sh/teste.ifsp.edu.br/key.pem  \
    --fullchain-file /etc/apache2/acme.sh/teste.ifsp.edu.br/fullchain.pem \
    --reloadcmd     "service apache2 force-reload"

    Feito isso já pode configurar os certificados contidos na pasta criada, adicione as seguintes linhas na configuração do seu VHost:

    SSLCertificateFile "/etc/apache2/acme.sh/teste.ifsp.edu.br/cert.pem"
    SSLCertificateKeyFile "/etc/apache2/acme.sh/teste.ifsp.edu.br/key.pem"
    SSLCertificateChainFile "/etc/apache2/acme.sh/teste.ifsp.edu.br/fullchain.pem"
    HAPROXY

    Os procedimentos de configuração do HAProxy são os mesmos adotados para o certbot, conforme descrito acima, somente o comando para geração do certificado será alterado:

    acme.sh --issue -d teste.ifsp.edu.br --standalone --httpport 54321

    Deleção de certificados

    CertBot\Let's Encrypt

    Para deletar o certificado no certbot, execute o comando abaixo:

    certbot delete --cert-name teste.ifsp.edu.br
    ACME.SH
    acme.sh --remove -d teste.ifsp.edu.br

    Renovação automática do certificado

    CertBot\Let's Encrypt

    O certificado gerado pelo Let's Encrypt tem validade de 3 meses, para renova-lo automaticamente, execute os comandos abaixo:

    1) Teste para ver se  a renovação dos certificados ocorrerá sem erros:
    certbot renew --dry-run

    Se nenhuma mensagem de erro aparecer pode prosseguir para o próximo passo.

    2) Script para a criação da regra no crond:
    NGINX:
    #!/bin/bash
    touch /etc/cron.daily/letsencrypt
    chmod +x /etc/cron.daily/letsencrypt
    cat > /etc/cron.daily/letsencrypt <<DELIM
    #!/bin/bash
    /usr/bin/letsencrypt renew --renew-hook "/etc/init.d/nginx reload"
    DELIM
    APACHE2:
    #!/bin/bash
    touch /etc/cron.daily/letsencrypt
    chmod +x /etc/cron.daily/letsencrypt
    cat > /etc/cron.daily/letsencrypt <<DELIM
    #!/bin/bash
    /usr/bin/letsencrypt renew --renew-hook "/etc/init.d/apache2 reload"
    DELIM
    HAPROXY:

    Primeiro, devemos criar um script que fará a mesclagem dos certificados emitidos pelo LE, o HAproxy só aceita certificados em Bundles:

    vi /usr/local/bin/renew.sh
    #!/bin/sh
    
    SITE=teste.ifsp.edu.br
    
    # move to the correct let's encrypt directory
    cd /etc/letsencrypt/live/$SITE
    
    # cat files to make combined .pem for haproxy
    cat fullchain.pem privkey.pem > /etc/haproxy/certs/$SITE.pem
    
    # reload haproxy
    service haproxy reload
    chmod u+x /usr/local/bin/renew.sh

    Agora devemos alterar a porta do mini servidor wwb do certbot para utilizar outra porta que não seja a 80, evitando o conflito com o HAproxy:

    vi /etc/letsencrypt/renewal/teste.ifsp.edu.br.conf
    # Altere este linha
    http01_port = 54321

    Agora vamos agendar a renovação com o cron:

    crontab -e
    30 2 * * * /usr/bin/certbot renew --renew-hook "/usr/local/bin/renew.sh" >> /var/log/le-renewal.log

    ACME.SH

    Os certificados emitidos pelo acme.sh são renovados automaticamente a cada 60 dias e não necessitam de intervenção ou configuração extra.