Olaaaaaa pessoas, muito boa tarde/manhã/noite, espero que vocês estejam bem.
Trilha sonora enquanto eu escrevia esse artigo:
https://open.spotify.com/intl-pt/track/5dpDnd3Nnw5dRql80RcI7M?si=41eec3a4d5eb45e9
Neste artigo, vamos fornecer um combo de informações. Aprenderemos desde a configuração de um servidor HTTPS usando o Nginx, passando pela criação de um certificado autoassinado e, por fim, configuraremos o mesmo servidor para ser um Mutual TLS ou apenas mTLS.
Nota: Nesta primeira parte, aprenderemos como configurar um ambiente HTTPS usando o Nginx.
Para este tutorial, estou usando o Docker com o Docker Compose para orquestrar nosso ambiente local, facilitando assim o processo de configuração do ambiente. Afinal, em 2023, ninguém mais configura um servidor Nginx diretamente na máquina.
Configurando o ambiente
Começaremos criando nosso diretório de projeto:
mkdir projeto-mtls
Dentro da pasta, criaremos um arquivo docker-compose.yaml e uma pasta nginx que conterá tudo relacionado ao nosso servidor:
cd projeto-mtls
touch docker-compose.yaml # Arquivo do ambiente docker nosso.
mkdir nginx # Pasta que vai guardar tudo relacionado ao nginx
mkdir nginx/certs # Pasta que vai guardar nossos certificados.
Feito isso, agora começaremos a configurar nosso servidor.
Vamos criar um arquivo nginx.conf:
touch nginx.conf
Nele, configuraremos um servidor "simples" que retornará uma página HTML quando acessado em http://localhost:
server {
listen 80;
server_name localhost;
location / {
default_type text/html;
return 200 "<!DOCTYPE html><h2>Hello World!</h2>\n";
}
}
Agora, para testarmos se tudo está funcionando, configuraremos nosso docker-compose.yaml da seguinte forma:
version: "3.8"
services:
nginx:
container_name: proxy-mtls
restart: always
image: nginx
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./nginx/certs:/etc/nginx/certs
ports:
- "80:80"
- "443:443"
networks:
- sandbox
networks:
sandbox:
driver: bridge
Mapearemos a pasta nginx para dentro do container, para que as configurações e certificados sejam acessíveis no servidor:
docker-compose up # Inicializa os containers do Docker Compose.
Com o servidor ativo, acesse http://localhost:
Configurando o SSL
Agora que temos nosso servidor HTTP, precisamos configurar o SSL para começarmos a usar HTTPS nas requisições.
Para isso, precisamos gerar um certificado autoassinado.
Nota: Um certificado digital normalmente requer uma autoridade de certificação (CA) para validar sua autenticidade. No entanto, em casos de desenvolvimento, podemos atuar como a própria CA e assinar nosso próprio certificado, conhecido como "certificado autoassinado". Esse tipo de certificado não é válido em produção, mas é suficiente para ambientes de desenvolvimento.
Gerando a chave privada do certificado
Para gerar nosso certificado, usaremos o utilitário OpenSSL, amplamente utilizado para criptografia e segurança. Utilizaremos o comando a seguir para gerar uma chave privada:
openssl genpkey -algorithm RSA -out certs/localhost.key
Este comando utiliza o algoritmo RSA, amplamente empregado em sistemas de segurança, como SSL/TLS, para criptografar comunicações na web. O resultado será salvo em certs/localhost.key.
Gerando a Solicitação de Assinatura de Certificado (CSR)
Agora, usaremos o OpenSSL para gerar uma Solicitação de Assinatura de Certificado (CSR):
openssl req -new -key certs/localhost.key -out certs/localhost.csr
Essa solicitação contém informações necessárias para emitir nosso certificado. Informamos a chave privada a ser usada (certs/localhost.key) e o arquivo de saída (certs/localhost.csr).
Ao executar esse comando, você precisará fornecer várias informações sobre a autoridade do certificado e detalhes de contato, que serão enviados à CA para autenticar o certificado da empresa.
Dica bonus sobre geração de CSR
Se você precisa gerar vários certificados ou deseja ter um "modelo" para facilitar a geração de certificados no futuro, pode criar um arquivo de configuração contendo configurações padrão. Isso agilizará o processo de geração de certificados. Vamos criar um arquivo chamado template.csr.conf para ser nosso modelo: Dentro deste arquivo, colocaremos as seguintes informações: Nota: Eu não vou explicar aqui detalhes sobre esse arquivo, mas um ponto legal é que você pode configurar vários endereços no Agora, execute o comando novamente, mas desta vez passando o arquivo de configuração: Observe que, mesmo pedindo que você preencha informações, os dados pré-definidos são os que definimos no nosso modelo, economizando tempo durante o processo.Ver dica
touch template.csr.conf
[req]
default_bits = 2048
default_keyfile = localhost.key
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_ca
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = BR
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Sao Paulo
localityName = Locality Name (eg, city)
localityName_default = Sao Paulo
organizationName = Organization Name (eg, company)
organizationName_default = Localhost Ltda
organizationalUnitName = organizationalunit
organizationalUnitName_default = Development
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = localhost
commonName_max = 64
[req_ext]
subjectAltName = @alt_names
[v3_ca]
subjectAltName = @alt_names
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = 127.0.0.1
DNS.2 = localhost
[alt_names]
para que esse certificado suporte vários dominios.
openssl req -new -key certs/localhost.key -out certs/localhost.csr -config template.csr.conf
Gerando o Certificado Autoassinado
Após criar a chave privada e a solicitação de assinatura de certificado, chegou a hora de atuar como CA e assinar o certificado. Use o seguinte comando:
openssl x509 -req -days 365 -in certs/localhost.csr -signkey certs/localhost.key -out certs/localhost.crt
Este comando gera o certificado a partir da solicitação de assinatura de certificado (CSR). O certificado terá validade de 1 ano e será salvo em certs/localhost.crt.
Entenda o comando: x509 é usado para manipular certificados digitais. -req indica que estamos trabalhando com uma solicitação de assinatura de certificado. -days 365 define a validade do certificado em 1 ano. Os próximos três argumentos (-in, -signkey, -out) especificam o caminho da solicitação de assinatura de certificado, da chave privada e do arquivo de saída.
Testando o SSL
Após gerar o certificado, precisamos testá-lo. Para isso, faremos algumas alterações no nosso arquivo nginx.conf para indicar o uso de HTTPS em vez de HTTP:
server {
listen 80;
server_name localhost;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/certs/localhost.crt;
ssl_certificate_key /etc/nginx/certs/localhost.key;
location / {
default_type text/html;
return 200 "<!DOCTYPE html><h2>Hello World with HTTPS</h2>\n";
}
}
Agora, qualquer requisição para http://localhost será redirecionada para https://localhost. Observe que estamos usando os atributos ssl_certificate e ssl_certificate_key para apontar o certificado e a chave do nosso servidor.
Salve as alterações e reinicie o servidor:
docker-compose down
docker-compose up
Ao acessar https://localhost, você receberá um aviso do navegador informando que o certificado de autoridade é inválido.
Isso é esperado, uma vez que nós mesmos assinamos o certificado. Para continuar, clique em "Avançado" e depois em "Prosseguir para localhost (não seguro)".
Pronto, agora temos nosso servidor HTTPS funcionando:
Até este ponto, já temos um servidor HTTPS funcionando perfeitamente. Agora, vamos para a parte do Mutual TLS ou mTLS.
Fechando as Portas com mTLS
Nota: O mTLS, ou Mutual Transport Layer Security, é uma extensão do protocolo TLS que autentica tanto o cliente quanto o servidor durante a comunicação na internet. Isso é feito por meio da troca de certificados digitais, onde cada parte verifica a identidade da outra. Esse nível adicional de autenticação reforça a segurança da comunicação, especialmente em ambientes sensíveis à segurança, como serviços bancários online e sistemas corporativos, protegendo contra ataques de intermediários mal-intencionados e garantindo uma conexão confiável e criptografada.
Para começar, criaremos um certificado para o cliente, seguindo os mesmos passos que fizemos para criar o certificado do servidor:
mkdir nginx/certs/clients # Vai guardar o certificado do nosso cliente
openssl genpkey -algorithm RSA -out certs/clients/certificado-do-cliente.key
openssl req -new -key certs/clients/certificado-do-cliente.key -out certs/clients/certificado-do-cliente.csr -config template.csr.conf
openssl x509 -req -days 365 -in certs/clients/certificado-do-cliente.csr -signkey certs/clients/certificado-do-cliente.key -out certs/clients/certificado-do-cliente.crt
Após gerar o certificado do cliente, precisaremos configurar nosso servidor Nginx para trabalhar com mTLS. Para isso, faremos algumas atualizações em nosso arquivo de configuração:
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/certs/localhost.crt;
ssl_certificate_key /etc/nginx/certs/localhost.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
ssl_client_certificate /etc/nginx/certs/clients/certificado-do-cliente.crt;
ssl_verify_client on;
location / {
default_type text/html;
return 200 "<!DOCTYPE html><h2>Hello World Secury</h2>\n";
}
}
Agora, adicionamos algumas configurações adicionais ao nosso proxy. ssl_client_certificate especifica o certificado do cliente (que o cliente deve usar ao fazer chamadas para o nosso serviço), e ssl_verify_client ativa a verificação.
Com essa pequena mudança, garantimos que apenas o cliente que possua este certificado conseguirá fazer requisições para nosso ambiente.
Requisições sem o certificado resultarão em um erro:
Agora, ao passar o certificado na requisição, a chamada será bem-sucedida:
Considerações finais
Espero que este artigo seja útil para quem deseja estudar configurações de ambientes e segurança.
Até a próxima.
Se tiver alguma dúvida ou comentário, deixe-os aqui, e vamos compartilhar conhecimento.
Top comments (0)