Archive for outubro \07\-03:00 2009

VPN Site-to-MultiSite Descentralizada com Tinc

7 de outubro de 2009

Em outro Post, fiz um pequeno artigo, mostrando uma das formas de se construir uma VPN Site-To-MultiSite, usando um centralizador. O Centralizador nada mais é do que um Daemon, responsável por encaminhar pacotes entre os firewalls, e distribuir informações de rotas/e outras miscelâncias afim de automatizar certas tarefas nos firewalls clientes. De fato, é um modelo muito interessante de se trabalhar, e cai bem em vários ambientes. Mas como toda solução, tem seus contras também. Inicialmente, infra-estrutura. Como o tráfego de dados, tem sempre que passar pelo nó central, a infra-estrutura de comunicação pode ficar cara. Caso não haja investimentos, ela pode ser lenta e instável, as vezes até inviabilizando a solução. Existe o problema do nó principal ficar off-line também. Desta forma, todos os outros nós perdem a comunicação (com o nó principal, e também com todos os outros).
Afim de não perder a conectividade total coberta pelo modelo centralizador, e evitar tais problemas de sobrecarga e super dependência, apresento este artigo utilizando o Tinc (http://www.tinc-vpn.org/), que é um Sistema de VPN Livre, com suporte a SSL, e roteamento automático de redes, onde os Firewalls sempre tentarão uma conexão direta entre os pontos, caso seja possível.
Dessa maneira, teremos um modelo de VPN praticamente “peer-to-peer“, e pouca dependencia de centralizadores (para tráfego de fato nenhuma, mais a frente explicarei melhor).

Vamos verificar esta solução…

Sobre a instalação: Neste artigo, não abordarei nenhum procedimento específico de instalação. Utilize o gerenciador de pacotes de sua distribuição, ou compile os códigos fontes, que podem ser obtidos no site oficial. Caso você opte por instalar via sources, tome o cuidado de instalar a libz, a liblzo2 e a LibSSL em seu sistema antes. Mesmo que você não pretenda utilizar criptografia ou compressão, elas são necessárias para a compilação (Notas do Readme).

Com o Tinc instalado, vamos começar a configuração. Neste artigo, atenderemos a seguinte topologia de rede:

Cenário Proposto - Estudo de Caso

Em geral, os pacotes e/ou processos de instalação das distribuições deixam o diretório de configuração do Tinc em /etc/tinc. Vamos tomar esse diretório como base neste artigo. Você pode criar divisões dentro do diretório de configuração, onde serão hospedados todos os arquivos de configuração, de determinada rede. Poderíamos ter daemons de VPN nos interligando a redes de distintas empresas (Não estou falando de sites, e sim, de conjuntos de sites, por empresa por exemplo). No nosso caso, criaremos apenas uma “rede” para o Tinc, que irá abranger nossos 3 sites.

O Tinc pode trabalhar com interfaces TUN ou TAP. Interfaces TAP são utilizadas para trabalhar como bridge, e TUN, como uma interface de tunelamento mais simples. Utilizaremos interfaces TUN neste artigo. A maioria das distribuições Linux, compilam o modulo tun (modprobe tun para carregá-lo) em seu kernel, ou o deixam como built-in. Se você mesmo compilou seu kernel, não se esqueça de conferir o suporte a interfaces TUN/TAP

No Firewall da rede A, vamos realizar alguns procedimentos.
Entre no diretório /etc/tinc e crie um diretório com o nome de “vpn”.
Dentro deste diretório, crie um arquivo com o nome de tinc.conf, com o seguinte conteúdo:

Name = NetworkA
Interface = tun0

Agora, crie um diretório com o nome de “hosts ” . Neste diretório, ficarão armazenadas todas as chaves públicas dos Firewalls participantes da VPN, inclusive a sua. Agora, vamos gerar a chave publica e privada deste servidor.

# tincd -n vpn –generate-keys

Confirme o nome do arquivo da chave privada e da pública apenas pressionando enter, confirmando os arquivos nos locais automaticamente indicados.
Caso você tenha a vontade/necessidade de alterar estes locais, você pode fazê-lo, porém, você vai precisar indicar estes arquivos nos arquivos de configuração. É recomendado manter assim, pois dessa forma, fica mais fácil e padronizada a instalação de novos nós a rede.

Please enter a file to save private RSA key to [/etc/tinc/vpn/rsa_key.priv]:
Please enter a file to save public RSA key to [/etc/tinc/vpn/hosts/NetworkA]:

Dentro do diretório hosts, agora existe um arquivo com o nome de NetworkA. Abra-o com o editor de textos. Você vai visualizar a chave pública. Acima dela, acrescente as seguintes linhas:

Subnet = 172.16.0.0/22
Address = 200.187.176.48
Compression = 10

# Esta rede local
Subnet = 172.16.0.0/22
# O IP Externo deste Servidor
Address = xxx.xxx.xxx.xxx
# Nivel de compressao ( 8 – Zlib, 9 – Best Zlib, 10 – LZO, 11 – BestLZO )
Compression = 10

Desta forma, seu arquivo deve ficar assim:

Subnet = 172.16.0.0/22
Address = xxx.xxx.xxx.xxx
Compression = 10

—–BEGIN RSA PUBLIC KEY—–
…..
—–END RSA PUBLIC KEY—–

No Firewall da Rede B, vamos praticamente repitir o processo:

Crie um diretorio “/etc/tinc/vpn” e dentro de vpn, crie um diretorio “hosts”.
Crie um arquivo com o nome de tinc.conf com o seguinte conteúdo:

Name = NetworkB
Interface = tun0

ConnectTo = NetworkA
ConnectTo = NetworkC

Gere as chaves:
tincd -n vpn –generate-keys

Edite o arquivo hosts/NetworkB

Adicione antes da chave:

Subnet = 172.16.4.0/22
Address = xxx.xxx.xxx.xxx
Compression = 10

Na Rede C, faça a mesma coisa, apenas alterando o arquivo tinc.conf para:
Name = NetworkC
Interface = tun0

ConnectTo = NetworkA
ConnectTo = NetworkB

E o adicionando a hosts/NetworkC

Subnet = 172.16.8.0/22
Address = xxx.xxx.xxx.xxx
Compression = 10

Os arquivos de configuração de cada rede já estão prontos. Agora, precisamos criar os arquivos de cofiguração do Tinc que serão invocados quando o daemon for inicializado, ou interrompido. Nestes arquivos, teremos que configurar as rotas de cada rede, para o túnel designado. Isso pode ficar entediante dependendo da quantidade de pontos da rede, justo que quando uma rede for incluída, teremos que fazer essas configurações em todas as outras ( Não temos mais um centralizador para informar rotas ).

Para ajudar neste trabalho, criei um pequeno script bash, que fará a leitura dos arquivos dentro do diretório hosts, já que lá, estão todas as informações que precisamos para configurar as rotas. De qualquer forma, sempre que incluirmos uma nova rede, precisaremos colocar seu arquivo de chave publica com suas informações de rede em todos os pontos mesmo.

O Arquivo que é invocado pelo Tinc em sua inicialização é o tinc-up.
Crie um arquivo com este nome no diretório onde você criou o tinc.conf, com o seguinte conteúdo:

#!/bin/bash
## Wrapper para o script tinc-inits

# Subindo a interface estabelecida no tunel. A variavel INTERFACE e implicita
ifconfig $INTERFACE 10.255.254.1 netmask 255.255.255.0 up

# Chamando script para configurar as rotas “dinamicamente”
/etc/tinc/vpn/tinc-routes start $INTERFACE
############

Observação Importante: Observe que a variavel INTERFACE não foi configurada em nenhum local do script. Ela é criada implicitamente pelo daemon, quando ele invoca o arquivo. Outra observação importante é o IP atribuído na interface. Considere este IP como o da NetworkA. Na NetworkB, coloque 10.255.254.2, e assim por diante sequencialmente. Se um firewall tentar falar com outro, a comunicação será por esses IPS, a menos que você influencie via NAT, logo, estes IPS não são meramente para desvio. Eles podem ser usada na comunicação entre os firewalls ( um com destino diretamente ao outro ).

Agora, crie um arquivo com o nome de tinc-down (invocado no encerramento do daemon), no mesmo diretório, com o seguinte conteúdo:

#!/bin/bash
## Wrapper para o script tinc-inits

# Chamando script para configurar as rotas “dinamicamente”
/etc/tinc/vpn/tinc-routes stop $INTERFACE

# Subindo a interface estabelecida no tunel. A variavel INTERFACE e implicita
ifconfig $INTERFACE down
########

Agora, vamos criar o script que é invocado no final de tinc-up e tinc-down. Crie um arquivo com o nome de tinc-routes, no mesmo diretório, com o seguinte conteúdo:

#!/bin/bash
###############
# Arquivo tinc-up. Invocado depois que o daemon do tinc subir para esta network
# Este arquivo tenta automatizar a tarefa de preparacao das rotas de outras networks
# Sem configuracoes especificas, ou necessidade de alteracao nas adicoes de novos nodes a
# rede. Por: Eduardo Frazao — edufrazao@gmail.com
###############

# Diretorio de configuracao base.
# Esta e a unica configuracao que precisa ser realizada neste arquivo
# Configure de acordo com a localizacao dos arquivos de configuracao da rede
BASE_CONFIG_DIR=”/etc/tinc/vpn”

## Antes de Inicializar o script, detectando acao solcitada

case $1 in

start)
ACTION=”start”
;;
stop)
ACTION=”stop”
;;
*)
echo “Parametros necessarios: Start ou Stop”
exit 1
esac

# Verificando se a interface foi informada
if [ “$2” = “” ]; then
echo “Interface do Tunel Nao informada”
exit 1
else
INTERFACE=$2
fi;

# Minha Rede
MY_NAME=$(grep Name $BASE_CONFIG_DIR/tinc.conf | cut -d “=” -f 2)
# IP na Interface do tunel
TUN_IP=$(/sbin/ifconfig $INTERFACE | grep “inet addr” | cut -d “:” -f 2 | cut -d ” ” -f 1)

# Configurando rotas para os arquivos clientes, exceto o local
for nets in $(grep Subnet $BASE_CONFIG_DIR/hosts/* | grep -v $MY_NAME | cut -d “=” -f 2);
do
if [ “$ACTION” = start ]; then
ip route add from any to $nets via $TUN_IP dev $INTERFACE
else
ip route delete from any to $nets
fi;
done;
###################

Agora, torne os scripts executáveis:
# chmod +x tinc-up tinc-down tinc-routes

Pronto. Desta forma, finalizamos os arquivos de configuração. Observe que montei estes scripts apenas com a intenção de facilitar a manutenção das rotas, e o crescimento da rede. Não sou muito bom com scripts bash. Entenda que basicamente, o sistema invoca tinc-up e tinc-down, e você pode trabalhar esses arquivos da forma que achar mais conveniente para refinar as configurações de rede necessárias a seu ambiente. O Tinc também pode invocar scripts por clientes (quando se conectam), verifique man tinc.conf para mais detalhes.

Pronto. Antes de continuar, apenas uma nota sobre o parâmetro ConnectTo do arquivo tinc.conf: Este parâmetro, indica em quais redes os daemons devem ser conectar inicialmente. Mesmo que o trafego dos dados seja descentralizado, os daemons fazem conexões iniciais em hosts preestabelecidos. Assim que conseguem realizar uma conexão, eles passam a poder receber conexões de outros daemons da rede. Todavia, como vocês devem ter notado, é possível passar mais de um host para a conexão incial. E pode ser qualquer host da Rede. Isso não fará com que o trafego da rede acabe passando por este host indicado. Isso só aconteceria, se fosse impossível que a rede que está tentendo se comunicar, pudesse falar com seu destino, e por acaso, o host estabelecido em ConnectTo conseguisse. Sempre que possível, o Tinc tentará estabelecer uma conexão direta com o firewall de destino. Dessa forma, você pode eleger alguns hosts na rede, para serem configurados no ConnectTo dos outros clientes, e assim, manter uma redundancia desses valores. A NetworkA, é a única que não precisa deste parâmetro. É como se fosse um pseudo-server da rede, apenas aceitando conexões.

Finanlizando a configuração do Tinc: Agora, já temos todas as chaves prontas, e as configurações são apenas as realizadas acima. Claro que existem mais parâmetros que podem ser configurados (man tinc.conf). Isso depende de cada necessidade, porém, para nosso modelo já basta. O que precisamos fazer agora, é copiar as chaves publicas de todos os hosts uns para os outros. Ou seja, copiar hosts/NetworkA, para dentro do diretorio hosts do servidor de Network B e C. E vice-versa em todos.

Depois de feito isso, o Tinc já terá o conhecimento de onde fica cada rede, e a chave pública para se conectar a cada uma delas.

Usando este modelo descentralizado, teremos uma VPN como neste diagrama:

Diagrama - VPN Descentralizada

Feito isto, finalizamos as configurações. Considere as questões de firewall, para permitir as conexões dos daemons entre si, e também as passasges dos pacotes de uma rede para outra. Por padrão, o Tinc utiliza a porta 655 em TCP para estabelecer suas conexões (handshake TLS), e a porta 655 em UDP para transmitir os dados, ou seja, libere os dois protocolos para esta porta.

——————–

Espero que este artigo te ajude de alguma maneira. Quem quiser, pode postar comentários, ou entrar em contato por email!

Um abraço,

Eduardo Frazão / edufrazao – at – gmail.com