Como criar VPNs caseiras
Tags: vpn
Published: 2024-03-25 15:38:40

Muitas vezes para evitar problemas de rotas, disponibilidade de conteúdo ou se conectar em uma intranet se faz necessário o uso de VPNs. Normalmente isso é feito a partir de soluções proprietárias, entretanto também é possível criar uma VPN manualmente, utilizando uma máquina que esteja exposta na internet. Isso é o que eu tentarei mostrar nesse artigo.

## Atenção 0
Por mais que seja um sistema de infraestrutura caseiro é bastante difícil fazer com o que o custo do sistema seja zero, devido ao requisito de se ter exposição na internet. A maneira mais fácil de se fazer isso é utilizando soluções de cloud que terão um custo atrelado.

## Atenção 1
Não recomendo a utilização desse tipo de solução em operações do tipo Black Ops, devido à relação numismática que existe entre a implementação e o implementador.

## O que é uma VPN
Bom, afinal de contas o que seria uma VPN? Uma VPN é uma estrutura de rede utilizada primariamente para ligar redes à redes. Em situações comuns serve essencialmente pra acessar serviços que não estão expostos para fora de uma intranet.
![Tentativa de esquematizar uma VPN](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z2h3tamqki46tmbsmvo.png)

Óbvio que esse não é único uso que se pode fazer de uma VPN, uma vez que quando ocorre a saída de um pacote de uma das estremidades da comunicação o endereçamento do pacote muda (mascaramento), fazendo com que pareça que o endereço de origem do pacote é o do gateway da rede de saída.

O leitor mais atento pode se perguntar qual a diferença entre uma VPN e outras tecnologias comuns à língua de redes tais como NAT (Network Address Translation) e Proxy. O que ocorre é que tanto a tecnologia de NAT como Proxy tratam-se de camadas transparentes de indireção de fluxo, ou seja qualquer adversário que desejar realizar ataques visando a identificação de tráfego, tais como spoofing ou sniffing, o que não pode ocorrer de maneira tradicional quando se utiliza VPNs visto que todo o tráfego é posto sob a égide de um esquema criptográfico. Dessa maneira uma VPN teria um funcionamento mais parecido com o seguinte:

![Esquemático de funcionamento de VPN](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15u9hcepvy2dk5hr6ib8.png)

Afim de criar uma VPN caseira vou utilizar um servidor que tenha um IP fixo que eu possa acessá-lo a partir da web. Para tanto vou utilizar um servidor virtual EC2 da AWS, e uma máquina virtual sob NAT na minha rede local, e conectá-las a partir do Wireguard.

## O que é o Wireguard?
O Wireguard é um conjunto de utilitários de VPN que pode ser instalado na maioria das distribuições Linux, operando na camada 3 do modelo OSI (camada de rede), tem implementações tanto no kernel space, como no user space.

## Porque o Wireguard?
Existem outros utilitários que servem aos mesmos propósitos do Wireguard, tal como o OpenVPN, e por mais que o Wireguard não seja considerado "production-ready" eu considero mais simples de ser configurado e mais fácil de ser utilizado em operações rápidas.

## Como Funciona
Na sequência vamos ter duas máquinas cliente e servidor, entretanto também usarei os termos peer e peer de forwarding.
A sequência de passos (em alto nível)que deve ser seguida afim de estabelecer um túnel de VPN entre duas máquinas é a seguinte:

1. Criar as chaves (pública e privada) tanto no cliente como no servidor
2. Adicionar as configurações substituindo os locais de chave pública e privada
3. Iniciar o serviço no servidor, subindo uma nova interface de rede
4. Iniciar o serviço no cliente, subindo uma nova interface de rede e fechando o túnel

## Enough talk, show me the Cipher
Bom, a primeira coisa que deve ser feito é verificar se o servidor tem as configurações requeridas para se fazer o mascaramento de pacotes. No arquivo _/etc/sysctl.conf_ verificar se existe a seguinte definição:

```
net.ipv4.ip_forward = 1
```
E em seguida executar o recarregamento dos parâmetros de kernel:

```bash
sysctl -p
```
Então deve-se executar tanto no peer como no peer de forwading os seguintes comandos para gerar as chaves pública e privada:

```bash
umask 077 # A permissão de acesso deve ser restrita apenas ao root
wg genkey > privatekey # gera chave privada
wg pubkey < privatekey > publickey # gera chave pública
# move as duas chaves para o diretório do wireguard
# para facilitar a configuração
mv privatekey publickey /etc/wireguard
```
Feito isso basta criar os dois arquivos de configuração (recomendo utilizar o padrão _nome_interface_a_ser_criada.conf_), começando pelo arquivo de configuração do servidor:

```
# cat /etc/wireguard/wg0.conf 

# Nessa seção são definidas todas as configurações da interface de rede
[Interface]
Address = 10.10.42.1/24
SaveConfig = true 
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
# Chave privada do servidor
PrivateKey = PRIVATE_KEY_SERVER
# Nas seções de peer (podendo ser mais de uma)
# são feitas as configurações do cliente
[Peer] 
# Chave pública do cliente
PublicKey = PUBLIC_KEY_CLIENTE
# Lista de IPs que o cliente pode receber
AllowedIPs = 10.10.42.2/32
```
Foram muitas informações inseridas no arquivo anterior mas eu gostaria de dar um destaque especial em algumas variáveis:

- Address: Endereço da interface de rede que subirá (no caso a wg0)para fazer o mascaramento de IP
- PostUp, PostDown: são duas seções que executam comandos antes e depois que a interface de rede é criada e destruída respectivamente, podem ser muito úteis para configurar regras de filtro de pacotes como no exemplo acima
- ListenPort: Porta UDP que será aberta para o estabelecimento de túneis de VPN
- AllowedIPs: Lista de IPs que o cliente pode atribuir a si mesmo estabelecendo a conexão.

Já no cliente a configuração, sim é preciso fazer uma configuração para cada um dos clientes, é bem mais simples:

```
[Interface]
# Chave pública do cliente
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.10.42.2/24
[Peer]
PublicKey = YOUR_SERVER_PUBLIC_KEY 
AllowedIPs = 0.0.0.0/0
Endpoint = SERVER_PUBLIC_IP:51820
PersistentKeepalive = 20
```
No cliente a diferença mais notável é as seções de Endpoint e PersistentKeepalive:

- Endpoint: Indica em qual IP ou URI seguido da porta UDP o peer de forwarding deve ser acessado, a maneira mais simples de se configurar essa seção é utilizando um IP fixo
- PersistentKeepalive: Indica o intervalo de tempo em que um pacote de KeepAlive será enviado para servidor (no caso do exemplo 20 segundos), necessário caso o cliente tenha o seu IP mascarado por um NAT

Por fim, basta subir as duas interfaces de rede tanto no cliente como no servidor com o comando:

```bash
systemctl start wg-quick@nome_da_interface
```
_**Et voilà**_, a interface foi criada e todo o tráfego do cliente está sendo mascarado pelo servidor. Para testar o funcionamento basta executar uma resolução de IP e verificar que o IP de saída é o mesmo IP público do servidor:

```bash
$ curl ifconfig.me
PUBLIC_SERVER_IP
```

## Show me the money
Vale a pena pensar qual o custo de se fazer esse tipo de coisa em uma cloud. Utilizando um servidor EC2 nano temos um custo/hora de 0.0058 dólares, ou seja o custo/mês é de 4.176, não é caro mas se for deixado ligado 24 horas por dia pode ser comparável a soluções de VPN que existem no mercado.

A grande vantagem de se fazer esse tipo de manipulação é que não existe necessidade de se deixar obrigatoriamente 24 horas e desse jeito é possível chegar a valores bem irrisórios ao longo de um mês.

## Everybody wants to rule The World
Em resumo, criar uma VPN caseira pode se mostrar uma boa alternativa à soluções proprietárias, especialmente se o usuário gostaria de controlar os seus custos. Como um amigo meu gostava de falar:

> "O que as pessoas procuram é facilidade, mas o que elas realmente querem é controle."

Criar uma VPN caseira é uma forma de se atingir esse controle.

## Referências
[What is VPN](https://www.cisco.com/c/en/us/products/security/vpn-endpoint-security-clients/what-is-vpn.html)
[Difference between VPN, NAT and proxy](https://www.quora.com/What-is-the-difference-between-a-VPN-server-NAT-and-a-proxy-server#:~:text=VPN%20Example%3A%20The%20user%20can,using%20the%20VPN%20Technology%20anonymously.&text=NAT%20is%20Network%20Address%20Translation,network%20to%20a%20public%20network.)
[Wireguard Home](https://www.wireguard.com/)
[Ubuntu Wiki Wireguard](https://web.archive.org/web/20240221012556/https://ubuntu.com/server/docs/wireguard-vpn-defaultgw)
[Debian Wiki Wireguard](https://wiki.debian.org/WireGuard)
[Manual do wg-quick](https://man7.org/linux/man-pages/man8/wg-quick.8.html)