Configurando uma VPN no GCP com DNS e certificados Let’s Encrypt para serviços internos: Parte 3 criação de certificados Let’s Encript

If you have built castles in the air, your work need not be lost; that is where they should be. Now put the foundations under them.

Henry David Thoreau, Walden

Essa é a última publicação da série de 3, durante as duas publicações anteriores vimos:

Entretanto apesar dos serviços estarem seguros dentro de uma rede privada e acessíveis através do DNS, os certificados ainda são self-assign visto que não foram criados por autoridades aceitas pelos navegadores. Isso faz com que ao acessar um serviço com criptografia HTTPS o usuário receba uma mensagem aterrorizadora em seu navegador:

Em termos gerais não existe risco para o usuário, visto que o site foi desenvolvido internamente e que está dentro da VPN. O problema é que teríamos que avisar os usuários para aceitarem esse erro e continuarem para o site, essa instrução pode levar à criação de um comportamento de risco: possivelmente o usuário passará a aceitar erros de certificado mesmo em sites que não sejam internos, teria que acreditar que o usuário tem o bom senso de distinguir quais erros de certificado aceitar ou não… nunca acredite no bom senso do usuário.

Para criar os certificados de forma segura é possível utilizar os provedores de domínio como o Google, Go Daddy entre outros, mas também é possível utilizar o Let’s Encrypt. Let’s Encrypt é uma fundação sem fins lucrativos que emite certificados de graça. Os certificados Let’s Encrypt apresentam validade de 30 dias, isso significa que a cada 30 dias o certificado terá que ser renovado. É possível fazer isso manualmente, mas daria uma trabalheira sem fim todos, outra alternativa é utilizar o certbot e os desafios ACME.

Quem tem pelo menos uns 30 e pouco lembra dos lendários produtos ACME… parece que eles melhoraram bastante, o Let’s Encrypt ACME realmente funciona. Giff extraído de giphy.com

 

Let’s Encript e o desafio ACME

Para ser gerar um certificado utilizando o Let’s Encript é necessário que você prove que tem acesso/é dono do domínio para o qual está pedindo o certificado. O Let’s Encript possui uma maneira bem engenhosa para fazer isso, ele instrui você a colocar um retorno específico em um determinado end-point do servidor. Dessa forma quando o Let’s Encrypt fizer a chamada para o caminho especifica você deve responder como instruído, se isso ocorrer de forma correta fica provado que se é dono do domínio então o certificado pode ser criado. Abaixo segue mais ou menos um passo a passo de como isso acontece (é uma ideia mais ou menos geral, podem haver algum imprecisões…):

Requisição do certificado e recebimento das instruções para o desafio

O usuário solicita um certificado para um determinado domínio ao Let’s Encript, ao fazer isso ele recebe as instruções de como criar o desafio ACME no seu servidor. Esse desafio corresponde à um end-point que deve ser construído de acordo com as instruções.

Certbot requisita um certificado para o Let’s Encrypt que devolve a instrução para a criação do end-point para o desafio ACME

Normalmente para facilitar o processo de requisição e configuração dos desafios, é utilizado o certbot. Ele é uma aplicação que possui diversos plugins para configuração de diversos servidores como NGINX, APACHE, HAProxy, entre outros.

Criação do end-point ACME e validação do domínio

Após receber as instruções do Let’s Encrypt, o certbot configura o servidor para responder a URL especificada com a resposta adequada. O Let’s Encrypt então faz uma camada validando que o end-point foi corretamente configurado.

Ao receber a instrução do Let’s Encrypt o certbot faz a configuração do servidor de forma a responder corretamente o desafio ACME
Let’s Encrypt faz uma chamada verificando se o servidor foi corretamente configurado.

Disponibilização dos certificados e configuração do servidor para receber chamadas HTTPS

Após a validação do End-Point ACME, o Let’s Encrypt disponibiliza o certificado e o certbot remove o end-point ACME. O certificado recebido é usado para configurar a conexão HTTPS, e sendo que próprio certibot pode configurar o servidor para automaticamente redirecionar todas as chamadas para uma conexão segura usando HTTPS.

Após a validação ACME, o certificado é transmitido para o servidor da aplicação
O certbot usa o certificado que foi recebido para configurar o servidor usar comunicação segura através do HTTPS

Isso funciona super bem para aplicações que estão abertas à internet, os certificados são reconhecidos como confiáveis e o próprio certbot pode ser adicionado à um processo cron (ou algo do tipo) para que renove os certificados periodicamente. Mas existe um problema sério quando tenta-se implementar a validação ACME dentro de uma VPN.

Validação ACME dentro de uma VPN, humm…

Normalmente as VPNs permitem que seus usuários acessem a internet (talvez com algumas restrições), mas não permite que dispositivos da internet acessem os serviços internos da rede. Mas isso seria um problema para a validação ACME? Para a primeira etapa quando o certbot requisita as instruções para o Let’s Encrypt vai tudo sem problemas…

A primeira parte do desafio ACME flui sem problemas. O certbot é responsável por fazer a 1a chamada requisitando a configuração do desafio, assim não é bloqueado pelo Firewall.

O problema aparece na segunda parte do desafio… quando o let’s encript tenta encontrar o end-point com o ACME, ou é bloqueado pelo firewall, ou eventualmente não consegue chegar ao domínio pois esse foi configurado em um servidor DNS dentro da VPN. Por não conseguir validar o ACME e verificar que temos o controle do servidor, o Let’s encrypt não entrega os certificados.

Ao tentar validar a configuração do end-point ACME, o Let’s Encrypt encontra um firewall pelo caminho ou mesmo não encontra nada por não ter acesso ao DNS privado

Mas e se… abrirmos um buraco na VPN só para o Let’s Encrypt?

Uma alternativa seria abrir um buraco no Firewall para permitir a entrada da chamada de validação do Let’s Encrypt, isso teria que ser feito periodicamente junto ao processo que renova os certificados.

É possível criar uma regra de firewall que abre um buraco na VPN permitindo a entrada da chamada do Let’s Encrypt

Isso porém gera um outro problema, a criação do que pode ser chamado de backdoor. Backdoor é uma entrada secreta que não respeita as regras de segurança da principal, mas como sabemos de qualquer filme de aventura… toda porta secreta vai ser descoberta se houver alguém determinado a encontra-lá.

 

 

Toda backdoor é uma vulnerabilidade em potencial. Em segurança da informação, esconder não é proteger

 

 

Utilizando o desafio de DNS para a criação de certificados wildcard

Como vimos a criação de uma porta secreta com uma exceção no firewall pode ser um problema grave de segurança… mas como vamos conseguir validar o domínio para que o Let’s Encrypt nos disponibilize os certificados se não vamos abrir buracos em nossa VPN? Para nossa sorte existe uma alternativa à validação por ACME e que ainda por cima permite a criação de certificados do tipo wildcard (*.dominio.teste serviria para app1.dominio.teste, app2.dominio.teste e assim por diante), a validação de domínio através do servidor de DNS.

Ele segue o principio similar à validação ACME, mas ao invés de pedir um end-point no servidor final, o Let’s Encrypt tenta verificar se temos o controle do DNS público do domínio. Isso é feito de forma similar ao ACME, mas dessa vez em um determinado sub-domíno especificado pelo Let’s Encrypt deve ser retornada uma resposta do tipo TXT, que também é passada pelo Let’s Encrypt.

O certbot faz o pedido da validação por DNS para o Let’s Encrypt.
O certbot modifica as entradas do servidor de DNS utilizando uma API.
O Let’s Encrypt valida o domínio usando um sub-domínio buscando uma resposta TXT.

É possível verificar que através do método de validação por DNS não é necessário “abrir” buracos na VPN, pois o Let’s Encrypt consegue ter acesso ao servidor de DNS público. Para que o domínio esteja disponível para a validação é necessário que este seja comprado e desse forma deve ter um nome válido pela ICAM. Existem algumas alternativas como .internal, .net, entre outros que podem ser utilizados com o mesmo nome inicial. Um exemplo seria utilizar:

  • minhaempresa.com: Para todos os domínios que são abertos para os usuários da internet.
  • minhaempresa.internal: Para os domínios que são internos da VPN.

Outro ponto importante é que o servidor de DNS possua algum tipo de interface por API. A maioria dos servidores atuais apresentam essa funcionalidade, é possível ver quais já foram implementados com o certbot neste link.

Após a validação do DNS o certificado fica disponível para ser utilizado nos servidores dentro da VPN e é compatível com entradas do DNS interno usando o mesmo domínio wildcard que foi validado no servidor de DNS externo. Como falamos anteriormente, é uma boa política não mapear os domínios privados em servidores de DNS públicos, dessa forma o servidor público seria usado quase que só para a validação pelo Let’s Encrypt.

Disponibilização dos certificados para os diferentes servidores da VPN

Os certificados de wildcard podem ser utilizados por diversos sub-domínios, mas fazer o deploy usando um certbot para cada um deles levaria a um conflito entre os servidores: cada um invalidaria os certificados dos outros, não ia funcionar muito bem. Uma forma de contornar isso é criar uma aplicação separada responsável por renovar os certificados e disponibilizá-los através da Secrets Manager do GCP. Cada servidor então teria um processo que periodicamente baixaria o certificado em cada um dos servidores, dessa forma todos teriam o mesmo certificado que seria atualizado periodicamente pela aplicação dedicada.

A aplicação dedicada é responsável por periodicamente pedir a atualização do certificado através do desafio por DNS
Ao baixar o certificado, a aplicação dedicada posteriormente subiria este em um secrets no GCP
Por último um processo periódico em cada um dos servidores  baixa o certificado a partir do GCP Secrets Manager

Dessa forma é possível obter certificados validos, expedidos por uma autoridade conhecida (Let’s Encrypt) para domínios internos à VPN (terminados com .internal por exemplo) sem a necessidade de backdoors. Isso também remove o erro visto anteriormente para os certificados self-assigned e os domínios internos continuam podendo ser direcionados por um servidor de DNS privado dentro da própria VPN, assim sem a necessidade de mapear os IPs no servidor público.

Espero que o post tenha ajudado vocês na criação dos cerificados dentro de VPNs… foi um processo tortuoso de aprendizado, mas acho que no final ficou relativamente bem feito! Se um bom cientista de dados é também entender de segurança da informação, esse conhecimento deve se disperso por toda organização.

Compartilhar