Peer-to-site WireGuard VPN entre MacOS e Ubuntu Linux
Como fechar um túnel VPN entre um servidor Ubuntu Linux rodando sobre instância EC2 na AWS e um cliente MacOS.
Se você está lendo esse post eu provavelmente não preciso te convencer a usar uma VPN. Seja qual for o seu motivo, privacidade, segurança ou qualquer outro, o projeto WireGuard tem grandes chances de ser a solução mais simples para você.
WireGuard® é uma VPN extremamente simples, porém rápida e moderna, que utiliza criptografia de última geração. Seu objetivo é ser mais rápido, mais simples, mais enxuto e mais útil que o IPsec, evitando ao mesmo tempo sua enorme dor de cabeça. Pretende ter um desempenho consideravelmente melhor que o OpenVPN.
Neste artigo vou demonstrar como fechar um túnel VPN entre um servidor Ubuntu Linux rodando sobre instância EC2 na AWS e um cliente MacOS. Mas o mesmo princípio e muito provavelmente as mesmas configurações se aplicam para distintos ambientes, como um servidor caseiro ou uma instância na Linode e um cliente Linux ou Windows®.
Motivação
Eu escolhi o WireGuard principalmente por ser uma solução mais simples para o meu problema, que é ter um IP fixo quando estou acessando a Internet a partir da minha conexão móvel 5G. É comum em diversos países que mesmo você estando em um local fixo, seu endereço IP fique oscilando entre um pequeno conjunto de endereços da sua operadora de telefonia móvel. Isso torna problemático o acesso a sites onde há restrição de IP.
No meu caso, eu estava em busca de uma solução que pudesse ser facilmente instalada no meu MacOS. Evitei soluções pagas que em geral custam em torno de U$5/mês, pois com esse valor é possível ter uma instância de máquina virtual em Clouds como AWS ou Linode e de quebra resolver outros problemas além de possuir uma VPN. Também evitei soluções menos triviais de se implementar, como OpenVPN e IPSec.
Com isso em mente e também minha grande familiaridade com Linux, decidi dar uma chance ao WireGuard, o que acabou me surpreendendo muito positivamente. Além de simples, o site oficial alega que o WireGuard é mais performático, moderno e enxuto do que outras soluções:
[1] https://www.wireguard.com/papers/wireguard.pdf
Configuração
É possível implementar o WireGuard para atender a diversos cenários:
- Peer-to-site[2]: quando queremos conectar um computador à uma rede remota.
- Site-to-site[3]: quando queremos interligar duas redes.
Em qualquer um dos modos acima é possível escolher entre encaminhar todo o tráfego através do túnel VPN, o que o WireGuard chama de modo default gateway[4], ou limitar o encaminhamento para endereços ou intervalos IP específicos.
No meu caso, eu fiz a implementação peer-to-site combinado com default gateway. Dessa forma, quando estiver usando minha conexão 5G ou um WiFi em um local público, como em um evento ou em um café, todo o meu tráfego será enviado através da VPN.
[2] https://ubuntu.com/server/docs/wireguard-vpn-peer2site-introduction
[3] https://ubuntu.com/server/docs/wireguard-vpn-site2site
[4] https://ubuntu.com/server/docs/wireguard-vpn-defaultgw
Configuração inicial do servidor
No caso, tenho um servidor Ubuntu Linux rodando em uma instância AWS com IP público[5]:
- Instalação do pacote do WireGuard
sudo apt install wireguard
Este é um meta-pacote que por dependência irá instalar o wireguard-tools
, único pacote realmente necessário, já que o módulo do WireGuard já está presente no kernel Linux das distribuições Linux mais modernas.
- Criação do par de chaves pública/privada:
cd /etc/wireguard
wg genkey > wg0.key
wg pubkey < wg0.key > wg0.pub
Se o conceito de par de chaves ou formalmente criptografia assimétrica[6] é novo para você, pense que o que a chave pública criptografa, somente seu par privado é capaz de descriptografar e vice-versa.
Dessa forma, se Bob quer se comunicar com Alice, é necessário que cada um tenha ser par de chaves e que as suas chaves públicas sejam enviadas de um para o outro. Com isso, quando Bob quer enviar uma mensagem secreta para Alice, ele usa a chave pública de Alice para criptografar a mensagem. E assim, somente Alice, com sua chave privada, é capaz de ler a mensagem que foi encriptada com sua chave pública. Dessa mesma forma, quando Alice quer enviar uma mensagem para Bob, ela deve usar a chave pública de Bob para encriptar a mensagem e com isso, somente Bob será capaz de reverter o processo, descriptografando a mensagem.
Não é necessário manter os arquivos wg0.key
e wg0.pub
, muito menos nomeá-los dessa forma. Mas acho uma boa prática, já que é possível ter diversas interfaces WireGuard no servidor, cada uma com seu próprio par de chaves e configurações específicas, conectando peers ou redes de forma isolada.
[5] https://docs.aws.amazon.com/pt_br/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html
[6] https://stakey.club/pt/uma-breve-nocao-de-criptografia/#criptografia-assim%C3%A9trica
Configuração do cliente
Instalei a versão mais recente do App do Wireguard[7] e após abrir o app fui em "Add Empty Tunnel":
É possível nomear a interface como quiser, eu preferi manter o mesmo nome da interface do servidor, wg0
. O par de chaves no MacOS é gerado "automagicamente" pelo app. Acrescente as linhas faltando para que a configuração fique como a da figura abaixo:
- A Public key, que foi gerada automaticamente, deverá ser utilizada no bloco da seção
[Peer]
no arquivowg0.conf
que iremos criar mais adiante no servidor. - Já a PrivateKey não deve ser utilizada em qualquer outro lugar que não aqui, na configuração do túnel do app do WireGuard no MacOS.
- Em PublicKey na seção
[Peer]
, deve ser informado a chave pública gerada anteriormente no servidor, aquela que foi salva dentro do arquivowg0.pub
.
Demais configurações:
- Address: endereço IP da interface
wg0
do MacOS na VPN. - DNS: No mode default gateway o WireGuard remove os servidores DNS locais do sistema operacional. Por isso é necessário especificar pelo menos um endereço de DNS aqui.
- MTU: evita problemas com jumbo packages. No meu caso, após estabelecer o túnel VPN eu não conseguia acessar sites https sem definir essa opção com algum valor menos que
1420
. - AllowedIPs: quais endereços IP ou intervalos utilização a VPN,
0.0.0.0/0
significa todos os endereços IPv4. - Endpoint: Endereço IP público do servidor VPN e porta UDP onde o WireGuard estará escutando.
[7] https://apps.apple.com/us/app/wireguard/id1451685025
Finalizando a configuração no servidor
Agora que temos a chave pública do cliente MacOS, podemos finalizar as configurações do lado do servidor. O arquivo /etc/wireguard/wg0.conf
deve ter o seguinte conteúdo:
[Interface]
PrivateKey = IGvLFCZfDq1UZDKAkZ+cB+2AZzSdO/Sgp+26Tl+NG0A=
ListenPort = 51820
MTU = 1420
Address = 10.10.11.10/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens5 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens5 -j MASQUERADE
[Peer]
# MacOS
PublicKey = 493MTFesLa1xis32ilUpn4nmQD5lKck9FaeqeMvCkVk=
AllowedIPs = 10.10.11.100/32
Na seção [Interface]
:
- Em PrivateKey temos a chave privada do servidor gerada anteriormente e armazenada em
wg0.key
. - ListenPort, define a porta UDP que o processo do WireGuard irá aguardar por comunicação do peer.
- MTU, limita o tamanho máximo do pacote UDP. Eu tive problemas em estabelecer conexões https através do túnel VPN deixando esse valor ser calculado automaticamente.
- Address, endereço IP da interface
wg0
no servidor. - PostUp e PostDown, regras de firewall para liberar o tráfego de e para a interface
wg0
, além de fazer o mascaramento dos pacotes que saem pela interfaceens5
.
Na seção [Peer]
:
- Em PublicKey na seção
[Peer]
temos a chave pública do MacOS. Item 1 na figura "Interfacewg0
do cliente MacOS". - AllowedIPs, endereço IP do cliente MacOS.
Com isso, já podemos levantar a interface wg0
no servidor através do systemd
:
systemctl start wg-quick@wg0
Estabelecendo a conexão VPN
Com o servidor escutando na porta 51820/UDP, podemos estabelecer a conexão VPN a partir do cliente/MacOS:
Se tudo correu bem, você deve conseguir se comunicar com o servidor VPN e navegar na Internet através do túnel:
Tente acessar sites como https://ip-api.com/ ou https://ifconfig.me/ para confirmar que o seu IP de origem agora é o IP público do seu servidor e não mais da sua conexão móvel 5G ou do seu modem local.
Ou o comando tcpdump para "sniffar" por pacotes relacionados ao túnel VPN:
- tcpdump -n -i ens5 port 51820
- tcpdump -n -i wg0