Introdução

Embora hoje em dia seja extremamente simples criar na nuvem um ambiente temporário para estudos ou testes, eu ainda sou um pouco old school e tenho um pequeno computador que utilizo como laboratório, nada muito complexo, um antigo Dell OptiPlex Micro com Core i5, 16 GB de RAM e 500 GB de HD.

Nesse pequeno servidor eu costumo criar máquinas virtuais utilizando o KVM/Virt-Manager, ou containers utilizando o Docker, onde rodo serviços e aplicações que quero aprender como funcionam, fazer provas de conceito e realizar alguns testes com aplicações que já utilizo tanto no trabalho quanto em projetos pessoais.

Como estou em um ambiente controlado, acabo negligenciando um pouco as questões relacionadas a segurança e não utilizo certificados SSL/TLS nos serviços e na comunicação entre eles. Isso é algo que não deve acontecer no mundo real e frequentemente exige um trabalho extra pra validar as configurações e funcionamento com certificados na hora de implementar em produção.

Uma forma simples pra se acostumar a trabalhar sempre com certificados é criar uma Autoridade Certificadora local para criar e assinar certificados para as aplicações e serviços.

Criando uma Autoridade Certificadora local

O processo pra criar uma autoridade certificadora é bem simples e consiste basicamente de dois passos, o único requisito é ter o openssl instalado na máquina.

  1. Criar uma chave privada pra a Autoridade Certificadora.
  2. Criar um certificado root utilizando essa chave privada.

Criamos a chave privada com o seguinte comando.

# openssl genrsa -des3 -out localCA.key 2048

A execução do comando solicita que seja criada uma senha para a chave privada, essa mesma senha será solicitada na criação do certificado root.

Para criar o certificado root utilizamos o seguinte comando.

# openssl req -x509 -new -key localCA.key -sha256 -days 7300 -out localCA.pem

No comando acima o parâmetro -x509 indica que queremos gerar um certificado root auto-assinado e em conjunto com o parâmetro -days indica por quantos dias esse certificado será válido, além disso a execução do comando faz uma série de perguntas, como por exemplo o código de duas letras do país, o estado, a cidade etc.

Após esses dois comandos temos dois arquivos:

  • localCA.key - chave privada da autoridade certificadora local.
  • localCA.pem - certificado root da autoridade certificadora local.

Esses dois arquivos são necessários para assinar os certificados de serviços e aplicações.

Criando certificados para serviços e aplicações

Agora que já temos uma autoridade certificadora local, podemos criar certificados para serviços e aplicações, no caso vamos criar um certificado para um servidor web que vai responder no hostname local dev.lab.

O procedimento é bem semelhante a criação da chave privada e do certificado root.

Primeiro criamos uma chave privada para a aplicação.

# openssl genrsa -out dev.lab.key 2048

Na sequência utilizamos essa chave para criar um certificado do tipo csr, certificate signing request, ou seja uma solicitação de assinatura para o certificado.

# openssl req -new -key dev.lab.key -out dev.lab.csr

Novamente serão feitas algumas perguntas como o código de duas letras do país, estado, cidade etc.

Antes de assinarmos esse certificado com a autoridade certificadora local, precisamos criar um arquivo auxiliar com as informações de DNS do servidor web.

Vamos ciar o arquivo dev.lab.ext com o seguinte conteúdo

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
 
[alt_names]
DNS.1 = dev.lab

Agora já podemos solicitar que a autoridade certificadora assine o certificado da aplicação com o seguinte comando.

# openssl x509 -req -in dev.lab.csr -CA localCA.pem -CAkey localCA.key -CAcreateserial -out dev.lab.crt -days 7300 -sha256 -extfile dev.lab.ext

Será novamente solicitada a senha da chave privada da autoridade certificadora local.

Com os arquivos dev.lab.crt e dev.lab.key podemos configurar o servidor web para utilizar o certificado, no caso do NGINX usamos a configuração padrão.

server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  dev dev.lab;
    root         /usr/share/nginx/html;
    ssl_certificate "/etc/nginx/certs/dev.lab.crt";
    ssl_certificate_key "/etc/nginx/certs/dev.lab.key";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    include /etc/nginx/default.d/*.conf;

    location / {
    }

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}

Validando o certificado

Acessando o hostname dev.lab no navegador temos a mensagem de que a conexão não é privada.

erro no certificado

Recebemos essa mensagem porque, embora o servidor esteja utilizando um certificado, o navegador não reconhece a autoridade certificadora que assinou esse certificado.

Podemos resolver esse problema importando o certificado root, localCA.pem, que criamos anteriormente diretamente no navegador.

Após a importação do certificado o navegador passa a aceitar certificados assinados pela autoridade certificadora local.

certificado ok