Configurando uma VPN no GCP com DNS e certificados Let’s Encrypt para serviços internos: Parte 2 DNS

She was here on earth to grasp the meaning of its wild enchantment and to call each thing by its right name

Boris Pasternak, Doctor Zhivago (1957)

cited by Christopher McCandless in Into the Wild

O que é um DNS?

Antes de falar sobre como subir um servidor de DNS, vale a pena discutir o que é um servidor de DNS. Apesar de navegarmos nos sites utilizando seus endereços como www.murabei.com, a internet não é feita de nomes, mas sim de números que são os IPs. Para que qualquer computador possa se conectar a um outro computador (sendo bem simplista no caso) é necessário que cada um sabia os IPs envolvidos na comunicação, isso para que a mensagem chegue no computador de destino e também para que ela volte corretamente para o computador de origem.

Se a internet é feita de números e não nomes, como colocar www.google.com me faz acessar o site do Google? Bom ai entra o DNS, ele tem essa sigla por ser um servidor de nomes de domínio (DNS da sigla em inglês). Esse serviço é responsável por devolver o IP a partir do endereço do site.

No Ubuntu é possível verificar os IPs associados aos domínios usando o comando dig, segue abaixo alguns exemplos:

dig www.google.com
; <<>> DiG 9.16.1-Ubuntu <<>> www.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55816
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;www.google.com. IN A

;; ANSWER SECTION:
www.google.com. 93 IN A 142.250.218.228

;; Query time: 8 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: qui set 02 14:39:54 -03 2021
;; MSG SIZE rcvd: 59

dig www.bb.com.br
; <<>> DiG 9.16.1-Ubuntu <<>> www.bb.com.br
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17298
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;www.bb.com.br. IN A

;; ANSWER SECTION:
www.bb.com.br. 187 IN CNAME www.dc.bb.com.br.
www.dc.bb.com.br. 107 IN A 170.66.192.50
www.dc.bb.com.br. 107 IN A 170.66.11.10

;; Query time: 8 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: qui set 02 14:40:52 -03 2021
;; MSG SIZE rcvd: 95

Se você colocar no seu navegados os IPs acima, chegará ao site do Google e do Banco do Brasil, sendo que caso do Banco do Brasil é possível verificar um erro assustador ao abrir o site. Este erro sinaliza que o certificado de criptgrafia do site não está casando com o endereço (o certificado foi feito para www.bb.com.br e endereço está do IP).

Certo, entendemos o que é o DNS… ele dá nome para os IPs. Mas quem dá nome para os DNS? Ou melhor como encontramos os servidores de DNS? Bom, ai vem algo que talvez te deixe preocupado:

Quem (sem mudanças nas configurações dos dispositivos notes, celulares, etc…) faz isso é o seu roteador… WTF!!!!

Toda a navegação que você faz na internet é direcionada pelo DNS que é definido por aquela caixinha preta que pisca umas luzinhas (roteador). Gif extraído do giphy.

Mas o que significa isso? Quando você se conecta à internet na sua casa, seu computador pergunta para o roteador qual o DNS que ele deve utilizar para encontrar os IPs. Normalmente ele direciona para o DNS do próprio provedor de internet, o que é normalmente a busca mais eficiente. Mas qual o problema disso?

No caso de você estar na sua casa com seu roteador pessoal sem muitos problemas, mas também podemos pensar no caso de um ambiente público como cafés, bibliotecas ou mesmo hotéis/AirB&Bs. Neste caso não temos controle sobre o roteador, muito menos sobre quem foi responsável por configurar os servidores de DNS…

Existe um tipo de ataque específico que se chama DNS hijack. Nele um hacker, ou o seu próprio governo, ou seu próprio provedor de internet usa suas buscas de DNS para monitorar, direcionar para sites que não são os corretos ou mesmo encaminhar para sites de propaganda.

Outra possibilidade mais danosa (não que privacidade não seja um dano razoável) é o phising, neste caso você digita o site www.meubanco.com e o servidor de DNS hijackado te manda para um IP qualquer na dark-web. Este site é normalmente uma cópia do site original e você navega achando que está tudo certo… coloca a senha, seu usuário e sem medo de ser feliz… bom isso até limparem sua conta.

Outra coisa que pode acontecer é seu provedor fazer uma :shit: no DNS. Um tempo atrás um proeminente programador, CTO de uma das mais importantes startups de AI fez uma publicação enigmática:

Não estava conseguindo acessar nenhum domínio do tipo .org.

 

O que estava acontecendo é que o DNS sugerido pelo provedor de internet por algum motivo enigmático tinha deixado de identificar a todos os sites com terminação “.org”. Basicamente meu computador perguntava ao DNS o IP do bitbucket.org e o DNS respondia que nunca tinha ouvido falar nesse site impedindo a conexão.

Acho que deu para entender o que é um DNS, e como não configurar um DNS padrão para todos os colabores pode não ser uma boa ideia. Estamos no trabalho remoto, não pretendemos confiar no DNS que os roteadores dos AirB&B/café/bibliotecas me falam para os nossos colaboradores usarem.

Modificando o DNS padrão do Ubuntu

Em primeiro lugar vou mostrar como modificar o DNS padrão do Ubuntu 20 Mate. No Ubuntu as chamadas de DNS antes de serem encaminhadas para o servidor de DNS externo passam por um servidor de cache na própria máquina que roda no caminho 127.0.0.53 (padrão para DNS). Esse servidor faz com que chamadas para o mesmo endereço em intervalos curtos de tempo sejam direcionadas para o mesmo IP sem que o servidor do DNS externo seja ativado.

Falo isso porque, quando se procura pelo servidor DNS que está sendo utilizado o que você vai encontrar é o tal do 127.0.0.53.

cat /etc/resolv.conf

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "systemd-resolve --status" to see details about the actual nameservers.

nameserver 127.0.0.53

Para verificar qual DNS está sendo utilizado (por dentro do servidor de cache) é preciso rodar o systemd-resolve –status:

systemd-resolve --status

Global
  LLMNR setting: no 
  MulticastDNS setting: no 
  DNSOverTLS setting: no 
  DNSSEC setting: no 
  DNSSEC supported: no 
  Current DNS Server: 9.9.9.9 
  DNS Servers: 9.9.9.9 
  Fallback DNS Servers: 149.112.112.112

Aqui já podemos ver que o servidor DNS não é o especificado pelo roteador. Na empresa setamos todos os computadores para apontar para o DNS do Quad9. Quad9 é um servidor de DNS operado por uma fundação sem fins lucrativos com sede em Zurique, ele não mantem dados dos usuários e ainda por cima apresenta uma camada de segurança que impede o redirecionamento para sites que sejam identificados como maliciosos. Para modificar o DNS no Ubuntu é necessário editar o arquivo /etc/systemd/resolved.conf, inicialmente as linhas do DNS e FallbackDNS encontram-se comentadas, basta descomentar e adicionar os IPs dos DNS para torna-los padrão do sistema. No exemplo abaixo já encontra-se apontado para os servidores do Quad9.

[Resolve]
DNS=9.9.9.9
FallbackDNS=149.112.112.112

 

Criando um servidor de DNS privado para a VPN

Como vimos anteriormente, o servidor de DNS serve para dar nomes aos IPs. Quando se opera com serviços dentro de uma VPN, cada um deles é associado a um IP interno (normalmente começão com 10. alguma coisa). Sem uma entrada de DNS cada um dos usuários tem que acessar usando o IP diretamente, o que torna tudo muito mais chato. Fora isso, os certificados SSL são associados aos domínios, assim quando se tenta acessar um serviço HTTPS usando o IP o usuário recebe um mensagem de que o certificado não é valido (como vimos anteriormente no Banco do Brasil). É possível orientar os usuários a aceitar essas mensagens no caso de IPs internos, mas isso acaba criando uma cultura insegura de não respeitar avisos de segurança que pode se tornar uma vulnerabilidade.

Outra possibilidade seria mapear os IPs privados em servidores de DNS públicos. O problema disso é que literalmente os servidores são públicos, o que significa que qualquer pessoa da internet teria acesso aos números dos IPs da sua rede privada. Em segurança da informação existe uma máxima que ocultar não é proteger, mas também não precisa mostrar para todo mundo. Um mapa da rede interna não é uma vulnerabilidade, mas pode facilitar muito a vida de um invasor caso consiga acesso a rede.

Uma alternativa à navegar usando IPs com mensagens de certificados não validos ou abrir o mapa da rede para toda a internet é a criação de um servidor de DNS interno. Para isso é possível fazer o deploy um servidor de DNS dentro da própria rede privada, nós escolhemos o Bind9. O Bind9 é um servidor de DNS open-source mantido pela Internet Systems Consortium com código disponível no Github. Ele é um servidor de DNS completo (varias funcionalidades e diferentes plugins), mas só estamos interessados em mapear os IPs que vamos utilizar.

Como no passo anterior já criamos uma VPN e já podemos nos conectar a ela através do servidor de ponte, vamos deixar o Bind9 acessível apenas dentro da rede privada. Para fazer o deploy, vamos usar novamente o deployment manager do GCP.

Deployment do servidor bind9 usando o GCP

 

Para o servidor, pode ser escolhida a máquina mais barata do tipo E2 já que é um processo muito simples e por ser um DNS interno não vai receber muitas chamadas.

Configuração da máquina virtual para o servidor bind9

 

Na seção de rede, lembre-se de associar o servidor à rede e sub-rede que são utilizados pela VPN, o que permite os usuário usarem para nomear IPs da rede interna. Não vamos expor o servidor para a internet visto que servirá apenas para mapear os IPs internos da rede.

É necessário associar o servidor de DNS à rede que corresponde à VPN.

 

Por último, não é necessário abrir o firewall para receber chamadas externas por isso pode-se não habilitar as opções de firewall.

Após o deploy é possível verificar que é criada uma máquina virtual com as especificações acima e associado um IP da rede interna, esse será o nosso servidor de DNS local.

É possível verificar nas máquinas virtuais que o servidor está disponível no IP especificado, dentro da rede da VPN.

 

Temos agora que configurar o servidor, existem alguns passos iniciais descritos pela empresa que dá manutenção na imagem disponível no GCP, segue o link:

https://cloudinfrastructureservices.co.uk/how-to-setup-linux-dns-bind9-server-on-azure-aws-gcp/

Uma coisa que não encontrei na documentação é como mudar a senha do usuário root, isso pode ser feito diretamente no SSH com o comando sudo passwd root. Após logar na VPN, podemos acessar a interface Web do Bind9 através da porta 1000 usando o IP interno especificado (10.158.0.12 no exemplo acima).

Agora é só seguir os passos que estão no tutorial e cadastrar o primeiro domínio interno.

 

Como o DNS é nosso, podemos colocar qualquer valor no domínio com qualquer extensão. No próximo post vamos ver que preferencialmente devemos colocar alguma extensão que seja padrão assim conseguimos criar certificados usando o Let’s Encript. Mas por enquanto, estamos explorando o servidor de DNS… então podemos fazer alguns testes:

Nessa seção definimos um domínio que será resolvido pelo DNS. No caso estamos cadastrando o endereço “essedominio.internodavpn”.

 

A esse domínio, podemos cadastrar diversos sub-domínios… no caso vamos fazer uma brincadeira e cadastrar um domínio com o IP do google em google.essedominio.internodavpn.

Terminando isso precisamos reiniciar o servidor para aplicar as mudanças.

 

Bom agora rufem os tambores, vamos ver se nosso DNS está funcionando usando o dig…

# O @10.158.0.12 indica o IP do servidor DNS que dever ser utilizado para fazer a query do IP
dig @10.158.0.12 google.essedominio.internodavpn

; <<>> DiG 9.16.1-Ubuntu <<>> @10.158.0.12 google.essedominio.internodavpn
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37127
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: c6fd4936688919da0100000061320ffbc75895a6a4433a22 (good)
;; QUESTION SECTION:
;google.essedominio.internodavpn. IN A

;; ANSWER SECTION:
google.essedominio.internodavpn. 3600 IN A 142.250.217.228

;; Query time: 11 msec
;; SERVER: 10.158.0.12#53(10.158.0.12)
;; WHEN: sex set 03 09:07:23 -03 2021
;; MSG SIZE rcvd: 104
It is working!!!! Giff extraído de Giffy

 

Só que não… ainda não atualizamos o DNS do Ubuntu para enxergar o servidor que levantamos.

Atualizando o DNS do Ubuntu ao entrar na VPN

Nosso servidor de DNS está funcionando corretamente, mas o sistema ainda não o enxerga porque está olhando para o Quad9. Quad9 com certeza não conhece o domínio google.essedominio.internodavpn apontando para o IP do Google, assim dá o erro que não é possível encontrar o nome. O que pode ser feito é atualizar por script a lista de servidores de DNS ao subir a VPN na máquina e reiniciar a lista quando sair da VPN.

Para que isso seja feito podemos usar os comandos “up” e “down” dentro do próprio arquivo client.ovpn. Uma sugestão é adicionar as linhas abaixo logo no inicio do arquivo.

# Automatically generated OpenVPN client config file
# Generated on Thu Aug 19 01:21:47 2021 by openvpn-access-server-1-vm

#################################
# Adjust DNS for VPN connection #
script-security 2
up /etc/openvpn/up_script.sh
down /etc/openvpn/down_script.sh
#################################

E adicionar os scripts up e down no /etc/openvpn/. É importante que os arquivos up e down estejam com permissão de execução por isso vale rodar chmod +x /etc/openvpn/up_script.sh /etc/openvpn/down_script.sh.

/etc/openvpn/up_script.sh: Copia o resolv.template para o /etc/resolv.conf adicionando uma entrada para o servidor de DNS interno. Tenho que melhorar esse script, teoricamente se mudar de rede Wi-Fii, o arquivo /etc/resolv.conf vai regenerar e perder as configurações que foram passadas.

#!/bin/bash
cat /etc/resolv.conf | tee
cat /etc/openvpn/resolv.template | tee /etc/resolv.conf

/etc/openvpn/resolv.template: Informações que vão substituir os servidores de DNS do sistema, no caso a primeira linha seria o servidor de DNS interno (10.158.0.12 no exemplo atual), o segundo corresponde ao servidor de cache do Ubuntu que irá direcionar para o Quad9 posteriormente.

nameserver [ip do DNS interno]
nameserver 127.0.0.53

/etc/openvpn/down_script.sh: Regenera o DNS do sistema.

#!/bin/bash
resolvconf -u

Ao sair e entrar novamente na VPN o DNS deve estar funcionando corretamente:

# Não é mais preciso identificar o servidor DNS com o @10.158.0.12
dig google.essedominio.internodavpn

; <<>> DiG 9.16.1-Ubuntu <<>> google.essedominio.internodavpn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30216
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 871cc9504dfbd952010000006132192ee70e0dde8023ab5d (good)
;; QUESTION SECTION:
;google.essedominio.internodavpn. IN A

;; ANSWER SECTION:
google.essedominio.internodavpn. 3600 IN A 142.250.217.228

;; Query time: 12 msec
;; SERVER: 10.158.0.12#53(10.158.0.12)
;; WHEN: sex set 03 09:46:38 -03 2021
;; MSG SIZE rcvd: 104

Quando tentamos acessar o domínio google.essedominio.internodavpn recebemos a mensagem de segurança que o certificado não corresponde ao nome do domínio que estamos acessando. Isso ocorre porque o certificado está associado ao domínio www.google.com e estamos acessando com o google.essedominio.internodavpn.

Se você clicar em proceed…

Nós somos os Google! Vale notar o sinal no canto da barra de navegação avisando que a conexão não é segura, isso porque o nome do certificado e o domínio não estão batendo. Bom deu algum erro na navegação, mas melhor pararmos por aqui antes que os tiras fiquem na nossa cola!

Brincar com domínios públicos não costuma deixar as pessoas muito felizes… Extraído de giphy

Informação importante sobre segurança, deixe o servidor DNS fechado!

Se você é uma pessoa que está começando com os servidores DNS, tenha certeza que eles não estão abertos ao público!

Existe uma configuração específica de recursão no servidor, que caso mal configurada, pode ser utilizada por pessoas maliciosas para atacar outros sites com Deny of Service. A pior parte disso é que você pode ser responsabilizado judicialmente por ter deixado o servidor vulnerável!

https://us-cert.cisa.gov/ncas/alerts/TA13-088A

Próximos passos…

Agora temos uma VPN e um servidor de DNS interno que nos permite dar nomes para os IPs. Falta ainda configurar os certificados para que não tenhamos os erros de segurança dos certificados self-assigned. Para isso vamos usar o Let’s Encript usando a validação de wildcard do domínio através do DNS.

Após a aquisição dos certificados, eles precisam ser disponibilizados para os servidores dentro da rede interna. Para isso vamos usar os secrets do GCP e um processo cron para atualizar os certificados de forma periódica.

Compartilhar