De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Tiago Cruz
Data de Publicação: 16 de Março de 2006
VPN significa Virtual Private Network, usada amplamente para fazer um túnel seguro entre duas redes distantes, separadas pela internet. Os dados são criptografados antes de entrar no túnel e apenas a outra ponta conhece a chave para descriptografar o mesmo, criando um canal de comunicação relativamente seguro.
Este documento visa abranger os principais problemas de implementação de uma VPN, assim como suas soluções.
O PPTP (Point-to-Point Tunneling Protocol) é uma implementação de VPN baseado no protocolo GRE e na tecnologia PPTP. Seu funcionamento é semelhante ao de uma conexão dial-up: ele "disca" para um host conhecido, troca chaves através do protocolo GRE e conecta uma interface virtual (ppp) por onde a comunicação dentro do túnel ocorre. Para estabelecer a conexão é necessária a autenticação de um usuário, podendo ser local ou um já pré-existente em uma base LDAP como o Active Directory.
Ele possui a vantagem de ter sido "adotado" pela Microsoft, portanto funciona nativamente desde o Windows 95 até o atual Windows XP sem precisar instalar nada no cliente. Seria uma solução interessante: O cliente remoto com um notebook poderia conectar à nossa rede de uma forma segura, passando pelo firewall em Linux/ BSD e autenticando em nossa rede usando a mesma senha da rede local. Seria realmente bem bacana se não fosse as desvantagens do PPTP.
Ao mesmo tempo que é uma vantagem ter um protocolo mantido pela Microsoft, é também uma desvantagem devido a falta de segurança da empresa citada e seus produtos. Segundo o Marcolino Alexandre, "O protocolo PPTP possui uma série de falhas exploradas por hackers que possibilitam a invasão ou a indisponibilidade de servidores Windows. Tanto o projeto POPTOP como o MPD que fazem o trabalho de servidor PPTP para Linux e FreeBSD respectivamente, não são vulnerável à ataques de exploits para Windows, apesar do protocolo ainda ser vulnerável a indisponibilidade."
Mas o problema mais grave que eu percebi durante a implementação do PPTP é este descrito pelo Gleb Smirnoff: //"Masquarading GRE protocol, which is used by PPTP as transport, isn't simple. Not all NATs can do this. If you are going to server a lot of clients connecting from random places in the world, then you will face this problem time to time."//
Portanto, se algum dia seu cliente com o notebook estiver em algum hotel, aeroporto ou qualquer lugar do mundo conectado à Internet atras de um NAT de roteador, ele não conseguirá se conectar a sua rede. Configurar um firewall para rotear o protocolo GRE é extremamente trabalhoso, incluindo passos como a recompilação do kernel no Linux. Fora o fato de que alguns roteadores "encaixados" simplesmente não roteiam e ponto final. E o trabalho deve ser feito no roteador onde o cliente está, e não do seu lado, tornando-se impraticável pedir para que cada sysadmin faça isso em seu firewall antes que seu cliente precise de tal recurso.
Para ler mais sobre esta solução, favor consultar o artigo anterior chamado Soluções de VPN integrando Linux, FreeBSD e Windows.
O OpenVPN usa criptografia de chaves ao invés de usuário e senha para fechar um túnel de VPN. Segundo o Luiz Antônio Filho, ele "simplesmente pega a informação que ele precisa mandar para a outra ponta, criptografa ela, e manda pela internet por um pacote UDP. A grande vantagem, é que ele não tem muitos problemas para passar por firewalls, e por roteadores que fazem NAT."
Atualmente, o OpenVPN roda nas seguintes plataformas: Linux, Windows 2000/XP ou superior, OpenBSD, FreeBSD, NetBSD, Mac OS X, e Solaris. É, por assim dizer, um projeto Open Source licenciado pela GPL.
A parte da instalação está bem documentada no site oficial do projeto e traduzida para o Português do Brasil aqui.
Você pode encontrar pacotes pré-compilados para a maioria das distribuições Linux, ou ainda instala-lo através do /usr/ports/security/openvpn do FreeBSD. Se você preferir compilar "na unha" certifique-se de ter as bibliotecas de desenvolvimento do OpenSSL (algo como openssl-dev) instaladas no seu micro. O dispositivo TUN/TAP deverá estar compilado no seu kernel também, caso sua distribuição não o traga como padrão (está presente desde o kernel 2.4.7).
Antigamente, você tinha que gerar as chaves CA manualmente, assina-las, criar as chaves dos clientes e gerar os parâmetros Diffie-Hellman (utilizado para a troca das chaves criptografadas durante a execução). Eram uma série de comando complicados de decorar, mas agora o OpenVPN vem com uma série de scripts chamados easy-rsa junto em seu pacote, para tornar esta tarefa mais simples.
Você pode encontrar estes scripts em /usr/local/share/doc/openvpn/easy-rsa e é encorajado a copia-los para seu diretório de configuração do OpenVPN (algo como /etc/openvpn ou /usr/local/etc/openvpn).
Ja dentro do diretório apropriado, você deve editar o arquivo vars e personalizar suas informações. Após isso, pode seguir com os comandos:
# . ./vars # ./clean-all # ./build-ca
O último comando, buil-ca irá gerar seu Certificado de Autoridade (CA) usando as bibliotecas do OpenSSL. Os parâmetros serão lidos do arquivo previamente configurado (vars) com excessão do parâmetro Common Name, onde você pode colocar algo como "CA-OpenVPN".
Use o comando abaixo, respondendo a questão "Common Name" como anteriormente (você pode usar "server" neste caso). Deverá tomar cuidado também em responder "y" quando solicitado em "Sign the certificate? [y/n]".
# ./build-key-server server
Os comandos abaixos deverão ser utilizados para gerar a chave dos clientes, e você deve colocar este mesmo nome quando solicitado no campo Common Name.
# ./build-key mario # ./build-key maria # ./build-key renata
Importante: Cada cliente deverá ter um Common Name único!
Para aumentar ainda mais a segurança, recomendo usar o comando build-key-pass para que as chaves seram geradas com uma senha. Assim, o cliente deverá ter o certificado e deverá saber a senha para acessar sua rede.
Os parâmetros do Diffie Hellman deverão ser gerados da seguinte forma:
# ./build-dh
Nota: Isso pode demorar um pouco.
No subdiretório chamado "keys" você encontrará os arquivos gerados. Segue uma tabela falando sobre os principais arquivos:
Arquivo | Necessário por | Finalidade | Secreto |
---|---|---|---|
ca.crt | servidor + todos clientes | Certificado CA raiz | NÃO |
ca.key | máquina que assina as chaves | Chave CA raiz | SIM |
dh{n}.pem | somente servidor | Parâmetros Diffie Hellman | NÃO |
server.crt | somente servidor | Certificado do Servidor | NÃO |
server.key | somente servidor | Chave do Servidor | SIM |
mario.crt | somente mario | Certificado do mario | NÃO |
mario.key | somente mario | Chave do mario | SIM |
maria.crt | somente maria | Certificado da maria | NÃO |
maria.key | somente maria | Chave da maria | SIM |
renata.crt | somente renata | Certificado da renata | NÃO |
renata.key | somente renata | Chave do renata | SIM |
Agora você deverá copiar os arquivos para o diretório de configuração dos clientes ou servidores. A cópia deverá ser feita preferencialmente usando uma forma segura, pois a mesma garante a conexão do mesmo com a rede.
No servidor, copie as chaves para /etc/openvpn (Linux) ou /usr/local/etc/openvbd (FreeBSD). Nos clientes Windows, copie para "%programfiles%"/OpenVPN/Config.
Você pode ainda querer tira o o acesso de determinado cliente. Você pode fazer isso de pelo menos duas maneiras:
Coloque essa linha no server.conf:
client-config-dir ccd
Crie o diretório ccd e dentro dele um arquivo como esse:
# cat ccd/mario ifconfig-push 10.8.2.5 10.8.2.6
Assim, quando o Sr. Mario conectar ele irá pegar uma rota inválida e não vai conseguir acessar nossa rede. Uma maneira mais elegante de fazer isso é descrito abaixo:
Use o script contido no easy-rsa:
# . vars # ./revoke-full mario
E adicione essa linha no server.conf:
crl-verify crl.pem
Assim, o cliente irá falhar logo no "handshake". Apenas cerifique-se de copiar o arquivo crl.pem gerado dentro da pasta keys para o diretório de configuração do servidor!
O arquivo openvpn.conf poderá ficar assim:
# IP e porta do servidor local 200.222.222.222 port 1194 proto udp dev tun # Certificados gerados ca ca.crt cert server.crt key server.key dh dh1024.pem # Criar no diretorio cdd/cliente a configuracao # dele - ou uma invalida para trava-lo :) client-config-dir ccd # Rede que os clientes irão "pegar" server 10.8.0.0 255.255.255.0 push "route 192.168.0.0 255.255.252.0" push "dhcp-option DNS 192.168.0.19" # Neste arquivo serão guardados os IPs dos clientes # para conectarem com o mesmo IP da proxima vez ifconfig-pool-persist ipp.txt client-to-client # Ative para permitir dois clientes com o mesmo # certificado - não recomendável ;duplicate-cn keepalive 10 120 # Compressão, privilégios do cliente comp-lzo max-clients 15 user nobody group nobody # Logs e etc persist-key persist-tun status /var/log/openvpn-status.log log /var/log/openvpn.log log-append /var/log/openvpn.log verb 6
Ao iniciar, fique atento aos logs para ver se está tudo certo.
A instalação é bem simples: Basta instalar o arquivo openvpn-2.0.5-gui-1.0.3-install.exe e copiar os arquivos para sua pasta de configuração. Para simplificar mais ainda, escrevemos um arquivo de lote para facilitar a instalação em clientes remotos. Note que permissão de administrador se faz necessário para instalar este software.
@echo off REM OpenVPN Installer REM by Tiago Cruz REM Julio Soares REM 20 Jan 2006 @echo. echo Wait, starting instalation of OpenVPN... echo Always click in 'Next', 'Install', 'Continue Anyway' and 'Finish' start /wait bin/openvpn-2.0.5-gui-1.0.3-install.exe @echo. echo Wait, copying files... @echo. copy conf\*.* "%programfiles%"\OpenVPN\Config @echo. echo Done. You can access the VPN now. @echo. pause @echo.
Preparamos ainda um "pacote" zipado com arquivo a ser instalado dentro do diretório "bin" e as configurações no "config". Assim o usuário final apenas precisa descompactar o arquivo zip e clicar no install.bat 8-)
Um exemplo de configuração de um cliente Windows:
client dev tun proto udp remote 200.222.222.222 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt cert renata.crt key renata.key ns-cert-type server comp-lzo verb 3
Você deve ser capaz de conectar ao seu servidor, pinga-lo através do IP 10.8.0.1 e sua rede 192.168.0.0/22 também através da rota criada no arquivo de configuração do servidor, caso ele seja o gateway de sua rede.
Consulte o howto oficial para maiores detalhes sobre os assuntos aqui abortados.
Se você montar seu servidor de VPN em um host que não é o gateway da internet (por exeplo no 192.168.0.253) você precisará criar uma rota em seu gateway pelo seguinte motivo:
Quando o cliente conectado via VPN com o IP 10.8.0.1 envia um pacote de ICMP para o host 192.168.0.11. O pacote chega até o host, mas ele não tem rota para a rede 10.8.0.0/24 portanto ele devolve o pacote para o gateway da rede. Se este gateway não tiver rota também, o pacote será descartado. Portanto, é necessário que o gateway envie os pacotes para o servidor de VPN.
Em um servidor FreeBSD a rota ficaria assim:
route delete 10.8.0.0 &> /dev/null route add -net 10.8.0.0 -netmask 255.255.255.0 192.168.0.253 &>/dev/null
Em um servidor Linux seria assim:
route add -net 10.8.0.0 netmask 255.255.255.0 gw 192.168.0.253 eth0
Se a rede de sua empresa é 192.168.0.0/24 e a do cliente também, ao fechar a VPN o cliente irá ficar com duas rotas para o mesmo destino. No caso do Windows, o pacote não irá para uma rede e nem para a outra :-)
Será necessário remapear a rede de destino para "enganarmos" o sistema operacioal, fazendo parecer que temos duas redes distintas: a do cliente 192.168.0.0/24 e a do servidor que também é 192.168.0.0/24 ficará como sendo 192.168.1.0/24.
Utilizando o iptables/ netfilter do Linux:
iptables -t nat -A PREROUTING -d 192.168.0.0/24 -j NETMAP --to 192.168.1.0/24
Utilizando o PF do Free/OpenBSD:
vpn = "tun0" ... set loginterface $vpn2 ... binat on $vpn from 192.168.0.0/24 to any -> 192.168.1.0/24 ... pass in on $vpn from any to any keep state pass out on $vpn from any to any keep state
Assim, para o cliente via VPN alcançar o host 192.168.0.32, ele deverá procurar por 192.168.1.32.
Outra coisa, no arquivo de configuração do OpenVPN deverá conter a rota adequada:
push "route 192.168.1.0 255.255.255.0"
No lugar da rota antiga:
push "route 192.168.0.0 255.255.255.0"
Você verá algo assim no tcpdump:
54. 224700 rule 26/0(match): pass in on tun0: 10.8.0.6 > 192.168.0.32: ICMP echo request, id 1024, seq 13568, length 40
Você pode encontrar mais informações neste artigo chamando Dirty NAT Tricks, escrito pelo Nick Martin.
Caso você tenha algum problema durante a operação, será necessário acompanhar os logs do aplicativos, bem como utilizar a ferramenta tcpdump para ver o que está acontecendo com os pacotes. Os logs do firewall também podem ajudar neste caso, assim como o comando netstat -nr para acompanhar se os pacotes estão dando match nas rotas propostas.
Você pode ainda contar com a ajuda de algumas listas de discussão, como as listadas abaixo:
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários