certificado

Automatizando a geração de certificados SSL locais para ambientes de desenvolvimento

Sabe aquele projeto que você está iniciando o desenvolvimento e já deixou tudo configurado pra ser acessado apenas via HTTPS no intuito de refletir como será em produção? Aí você configura um virtualhost para acessá-lo, mas ao entrar:

Essa é a imagem que melhor define o sentimento de “a pain in the ass“. A primeira coisa que a gente pensa é: e se eu gerar um certificado self-signed? Bem, pode resolver o problema no sentido do navegador te permitir acessar o domínio (com você colocando uma exceção pra ele), mas ainda assim, ele continua dizendo que a conexão não é segura:

E isso é uma coisa que incomoda pra caramba (pelo menos a mim :P). O problema é que os navegadores não conseguem reconhecer a autoridade de certificação de um certificado self-signed gerado da forma tradicional.

E, para criar uma CA (certificate authority) e adicioná-la na root store do sistema (onde os certificados são gerenciados. No caso do macOS isso é feito no software Keychain), não é algo tão trivial de se fazer, como você pode visualizar nesse tutorial aqui:

https://gist.github.com/KennedyTedesco/143576402fd7d9b49fbdedc9e417e5f9

Mas, e se eu te contar que tem uma ferramenta que abstrai toda essa dificuldade? Pois é! É o que veremos a seguir.

Antes, entretanto, é bom pontuar que esse artigo foi escrito para quem já tem o servidor web configurado com uma virtualhost, com o domínio em questão em /etc/hosts apontando para o host 127.0.0.1 e que agora precisa fazer um certificado local ser devidamente validado nos navegadores. O artigo não entrará em detalhes de configuração de servidor, configuração de aplicações etc.

Docker - Fundamentos
Curso de Docker - Fundamentos
CONHEÇA O CURSO

Gerando certificados SSL locais assinados com a mkcert

A mkcert é uma daquelas ferramentas indispensáveis para se montar um ambiente de desenvolvimento que dê gosto de trabalhar. Ela abstrai toda a dificuldade e complexidade de gerar certificados, como também de gerar uma CA (certificate authority) local. A única coisa que a mkcert não faz é instalar o certificado no seu servidor local, mas isso nem é algo tão complicado de se fazer.

Primeiro de tudo temos que instalar a ferramenta. Se você usa macOS, o Homebrew pode ser utilizado:

$ brew install mkcert

Se você usa Windows, você pode usar o gerenciador de pacotes Chocolatey:

$ choco install mkcert

Se você usa Linux, na documentação da mkcert mostra como pode ser feito.

Instalando a CA:

Para instalar a CA na root store, basta executar uma única vez:

$ mkcert -install

Criando o certificado:

$ mkcert teste.test "*.teste.test" www.teste.test

Nesse exemplo a ferramenta criará um certificado que será válido para o domínio teste.test e para todos os sub-domínios de primeiro nível dele.

O resultado da execução será:

~> mkcert teste.test "*.teste.test" www.teste.test
Using the local CA at "/Users/kennedytedesco/Library/Application Support/mkcert" ✨

Created a new certificate valid for the following names 📜
 - "teste.test"
 - "*.teste.test"
 - "www.teste.test"

Reminder: X.509 wildcards only go one level deep, so this won't match a.b.teste.test ℹ️

The certificate is at "./teste.test+2.pem" and the key at "./teste.test+2-key.pem" ✅

Tanto o certificado quanto a chave privada foram salvos no diretório do meu usuário. Tendo o certificado teste.test+2.pem e a chave privada dele teste.test+2-key.pem, já conseguimos configurar, por exemplo, o nginx para servi-los.

Configurando os certificados no Nginx

Agora, é preciso que você copie o certificado e a chave privada para o local onde o seu nginx consiga ter acesso para carregá-los. Você pode até renomeá-los se quiser.

No final do bloco server do virtualhost do seu projeto, basta adicionar o caminho para eles:

ssl_certificate /etc/nginx/ssl/teste.test.pem;
ssl_certificate_key /etc/nginx/ssl/teste.test.key.pem;  

Por exemplo:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    index index.php;
    root /var/www/teste;

    server_name teste.test www.teste.test;
    access_log off;

    location / {
         try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }

    ssl_certificate /etc/nginx/ssl/teste.test.pem;
    ssl_certificate_key /etc/nginx/ssl/teste.test.key.pem;  
}

No Apache seria algo como:

SSLEngine on
SSLCertificateFile "/private/etc/apache2/ssl/teste.test.pem"
SSLCertificateKeyFile "/private/etc/apache2/ssl/teste.test.key.pem"

Exemplo em funcionamento no Firefox:

Use e abuse da mkcert. Happy coding!

Ah, se você precisa gerar certificados SSL para o seu servidor em produção, veja esse artigo: Gerando certificados SSL gratuitos com Certbot.

Para que serve o certificado SSL?

O número de pessoas que executam transações sensíveis na internet (como compras online, transações bancárias, etc.) cresce cada vez mais. Porém, com a facilidade que a internet trouxe em geral para a execução destas operações, os cuidados devem ser redobrados. Analisar e verificar os sites onde estas operações são feitas com o intuito de detectar se o site é confiável, real e seguro é algo essencial.

Por isso, aspectos relacionados a segurança em geral em aplicações web merecem uma atenção especial. A sensação de segurança que uma aplicação web passa a seus usuários é algo extremamente importante, pois inspira confiança e credibilidade. Uma aplicação web precisa garantir que é verdadeira e que as informações trocadas estarão criptografadas e seguras. Visando isso, a implementação de um certificado SSL torna-se algo essencial.

O SSL (Secure Socket Layer) é um mecanismo de criptografia com o objetivo de aumentar a segurança na troca de informações entre clientes e servidores, protegendo a integridade e veracidade do conteúdo que trafega na internet. O certificado garante que a informação do navegador chegará de forma segura desde um cliente (como um browser) até o servidor do site. Quando você coloca seu número de cartão de crédito em uma página que utiliza SSL por exemplo, os números serão codificados e embaralhados, dificultando que um invasor ou interceptador consiga ver o número de cartão de crédito informado.

HTTP - Fundamentos
Curso de HTTP - Fundamentos
CONHEÇA O CURSO

Com a utilização do certificado SSL, o endereço do seu site passa de HTTP para HTTPS, indicando que as informações trafegadas entre cliente e servidor ocorrerão através do protocolo SSL/TLS e que as informações serão criptografadas. Além disso, os browsers modernos passam a exibir o desenho de um cadeado antes da URL, fazendo com que o usuário saiba que a aplicação web é segura.

O HTTPS (sigla para Hyper Text Transfer Protocol Secure ou Protocolo de Transferência de Hipertexto Seguro) é uma derivação do protocolo HTTP com uma camada SSL/TLS adicional implementada, o que adiciona mais segurança ao HTTP. Como o HTTPS utiliza criptografia, as chances de um intruso interceptar as mensagens trocadas entre cliente e servidor e obter acesso ao conteúdo destas mensagens reduz-se consideravelmente, pois as mensagens passam a ser criptografadas através de certificados digitais. Quando falamos sobre aplicações web, essa criptografia é essencial: através do tradicional HTTP, as mensagens são trafegadas como texto puro, ou seja: caso um interceptador capture mensagens HTTP, este terá total acesso a seu conteúdo sem maiores dores de cabeça. Com o HTTPS e sua criptografia inerente, esse risco é drasticamente reduzido.

Além de deixar o seu site mais seguro e confiável, a utilização do certificado SSL traz um outro benefício: a otimização do SEO. São diversos fatores que influenciam o ranqueamento dos sites no Google, sendo que um destes fatores é justamente a utilização de SSL. Como o Google considera o certificado SSL um benefício importante para os usuários, ele prioriza isso ao selecionar os sites que aparecem na busca, melhorando o posicionamento do seu site.

Como ele funciona?

O ciclo de uma transmissão HTTPS começa com um certificado digital. Um certificado digital é como se fosse uma espécie de RG eletrônico, identificando a sua aplicação como sendo uma aplicação confiável e verdadeira. Certificados digitais devem ser obtidos através de entidades certificadoras (ou CAsCertification Authorities), pois somente estas têm as permissões necessárias para gerar certificados digitais válidos. É um processo muito parecido com o RG humano propriamente dito… Um RG não pode ser emitido em qualquer lugar: ele deve ser solicitado somente em locais autorizados a lidarem com a emissão de RGs e que tenham acesso aos sistemas estaduais e nacionais de identificação. É o mesmo cenário com certificados digitais, já que estes irão identificar sua aplicação dentro de toda a web. Algumas entidades certificadoras são Verisign, GeoTrust, Comodo e Amazon. O serviço de geração de um certificado é geralmente pago e deve ser feito peridiodicamente, pois os certificados possuem uma data de expiração. Também existem serviços que emitem certificados de maneira gratuita, como o Let’s Encrypt.

Um certificado é composto basicamente por duas partes: uma chave pública e uma chave privada que são geradas randomicamente pela entidade certificadora. A chave pública é utilizada para verificar os clientes que realizam as requisições, enquanto a chave privada é utilizada para a realização do processo de criptografia.

Quando você se conecta a um servidor que utilize HTTPS/SSL para a transferência de informações, o servidor irá responder inicialmente com a chave pública e o certificado associado à aplicação que está sendo acessada. Cabe ao cliente (como um browser), ao receber esta chave, verificar alguns pontos:

  • Se a chave pública não está expirada (o que ocorre quando o certificado já se encontra expirado);
  • Se a chave pública pertence realmente à aplicação que está sendo acessada;
  • Se o cliente consegue descriptografar a assinatura digital do certificado enviado, o que significa que aquela chave pública e aquele certificado são válidos.

Quando um destes pontos de verificação falha, o cliente (como um browser) aborta a conexão e mostra uma mensagem de alerta para o usuário parecida com a tela abaixo.

Caso todas as verificações ocorram com sucesso, o browser entende que a comunicação está sendo feita com um servidor confiável.

Quando o cliente detecta que a conexão é confiável, o cliente cria uma nova chave, chamada de chave de sessão ou session key. Com a chave de sessão criada, o cliente envia esta chave de volta ao servidor, porém, criptografada com a chave pública validada nos passos anteriores.

Quando o servidor recebe a chave de sessão do cliente, ele utiliza a chave privada (que nunca é trafegada entre as requisições) para tentar obter a chave de sessão informada pelo browser. Um conteúdo criptografado com a chave pública só pode ser descriptografado com a chave privada, o que garante a autenticidade e legitimidade das informações que são trafegadas criptografadas com a chave pública. Caso o servidor consiga realizar este processo, é enviado de volta ao cliente uma resposta de que “está tudo OK”, também chamada de ACK (acknowledgement ou reconhecimento). Esse processo todo é chamado de handshake, pois agora somente o cliente e o servidor têm conhecimento das chaves públicas e de sessão que foram trocadas. É como se o cliente e o servidor tivessem se identificado um com o outro e, após existir a confiança entre os dois, ambos apertassem as mãos e disessem: “sei que você é você mesmo de fato e, por isso, confio nas informações que vamos trafegar entre nós”.

A partir deste momento, o servidor passa a responder as informações de volta ao cliente criptografando-as com a chave de sessão que somente o cliente e o servidor têm conhecimento. O cliente passa a utilizar a chave de sessão para descriptografar as informações enviadas pelo servidor. Quando o cliente precisa enviar informações para o servidor, este utiliza também a chave de sessão para criptografar o conteúdo, enquanto o servidor utiliza a mesma chave (que somente este cliente e o servidor possuem conhecimento) para descriptografar o conteúdo.

Veja que o processo de confidencialidade é bem forte neste processo: se algum interceptador interceptar estas mensagens, este não terá a chave de sessão vinculada ao cliente para descriptografar as mensagens. Ele também não conseguirá obter esta chave de sessão, mesmo que ele tenha acesso à chave pública do certificado: não se esqueça que o conteúdo criptografado com a chave pública só pode ser descriptografado com a chave privada. A única maneira de um invasor conseguir descriptografar o conteúdo é se este, de alguma maneira, tiver acesso à chave privada do certificado do servidor ou à chave de sessão do cliente.

Um ponto interessante é que esse processo de criptografia que é utilizado no HTTPS é chamado por muitos de criptografia assimétrica, já que existem duas chaves de criptografia utilizadas durante o processo: uma estática, mas que fica escondida no cliente (no caso da chave privada) e no cliente (no caso da chave de sessão); e uma chave pública, cujo conteúdo só pode ser descriptografado justamente com a chave privada. Veja que esse processo é diferente da criptografia “tradicional”, que também é dita como criptografia simétrica, onde só existe uma chave estática para a realização do processo de criptografia e descriptografia.