Discuta este tópico no fórum

Se este conteúdo te ajudou, deixe um presente!

Mostrando postagens com marcador VPN. Mostrar todas as postagens
Mostrando postagens com marcador VPN. Mostrar todas as postagens

quarta-feira, 11 de abril de 2018

OpenWrt/LEDE: fazendo seus backups no roteador (e distribuindo-os): parte 3

Mais um artigo da série sobre o OpenWrt/LEDE. 

No primeiro artigo deste tema, comentei o que uma solução de backup deveria ter. Passei pela solução que usava anteriormente (crashplan) e uma brevíssima introdução aos recursos do borg. Depois apresentei a configuração do backup em um HD externo no seu roteador. Neste artigo, iremos implementar a sincronia entre repositórios.

Só relembrando, esse é o esquema do backup:


O computador roda o borg e copia os arquivos (amarelo) para um repositório no roteador. Esse repositório é acessado por CIFS e aponta para um HD externo conectado na USB. Em um segundo momento, um rsync sincroniza esse repositório com um destino remoto utilizando o rsync. O destino remoto também é um roteador com um HD externo conectado, mas poderia ser qualquer destino com suporte a rsync. A comunicação do rsync é feita dentro de uma VPN, que interliga o roteador de origem e destino do repositório.

Este artigo aborda a parte verde do diagrama.

Sincronizando repositórios


Já ouvi a estória do "eu tinha backup, mas perdi junto". Incêndio, roubo, descarga elétrica durante o backup, não são se preocupar em "não queimar" o HD externo do seu backup. E o backup parece ter um certo magnetismo que o atrai para próximo da fonte original da informação, em especial antes de eventos catastróficos.

Como já havia comentado na parte 1 deste assunto, distribuir geograficamente o backup de forma automatizada era um requisito. A opção foi utilizando o rsync sobre uma VPN, onde o repositório do backup, conectado no roteador (que sempre está ligado), é enviado lentamente para um outro armazenamento remoto, também conectado em outro roteador (que sempre está ligado).

A parte da VPN é assunto antigo. O rsync pode ser feito pelo SSH, com autenticação por chaves. Porém, isso exige um certo grau de confiança da ponta remota pois as mesmas chaves podem abrir uma sessão no roteador remoto. Outra opção é um serviço rsyncd. Apesar de não ter autenticação, você pode controlar pelo firewall e pela restrição do próprio rsyncd quem pode acessar esse serviço. Se somente o teu roteador puder conectar no roteador remoto, só você poderá apagar algo indevidamente.

No roteador que receberá a cópia:

roteador-remoto# opkg update
roteador-remoto# opkg install rsyncd

A configuração não foi UCIficada e deve ser feita diretamente em /etc/rsyncd.conf. Só adicionar:

/etc/rsyncd.conf:
(...)
[fulano@gmail.com]
path = /mnt/HD-externo-XYZ/backup/borg/fulano@gmail.com
read only = no
fake super = yes

O identificador fulano@gmail.com é arbitrário. Eu gosto de usá-lo pois o repositório normalmente terá mais de um cliente. E nada melhor do que o email para lembrar o nome do repositório. 

Agora, basta ativar e disparar o serviço:

roteador-remoto# /etc/init.d/rsyncd enable
roteador-remoto# /etc/init.d/rsyncd start

Opcionalmente, se já estiver usando o xinetd (por exemplo, para o scanner na rede - SANE), pode também usar o xinetd ao invés do serviço rsyncd:

service rsync 
{
disable = no
socket_type = stream
port = 873
protocol = tcp
wait = no
user = root
server = /usr/bin/rsync
server_args = --daemon
log_on_failure += USERID
}

E falta, agora, somente a rotina que envia do meu roteador-local para o roteador-remoto.

rsync --bwlimit=30k --partial --archive --delete --delay-updates --delete-after  /mnt/HD-externo-abc/borg/ roteador-remoto::fulano@gmail.com/

E se usar por cima do SSH:

rsync --bwlimit=30k --partial --archive --delete --delay-updates --delete-after  /mnt/HD-externo-abc/borg/ roteador-remoto:/mnt/HD-externo-XYZ/backup/borg/fulano@gmail.com/

A primeira opção --bwlimit limita a taxa de transferência para o rsync. Ajuste para sua realidade. Como eventualmente teremos múltiplos gigabytes para serem enviados, o processo pode durar dias. A recomendação é sempre deixar um tanto para outros fins. O --partial permite continuar o envio quando a conexão foi perdida. Eu gosto de usar o --delay-updates --delete-after para manter o repositório íntegro durante a cópia. Se espaço for um problema do outro lado e ele não aguentar armazenar a mais a diferença a ser enviada, pode usar o --inplace e --delete-before. E sempre, man é seu amigo.

Agora é só colocar na cron. Como o processo pode rodar "por dias", é importante que ele não volte a rodar se o rsync anterior ainda estiver em execução. Por isso, podemos melhorar o comando usando o comando "lock":

lock -n /tmp/rsync.lock && { bwlimit=30k --partial --archive --delete --delay-updates --delete-after  /mnt/HD-externo-abc/borg/ roteador-remoto::fulano@gmail.com/; lock -u /tmp/rsync.lock; }

Se rodar novamente este comando enquanto a execução anterior ainda estiver em curso, você vai receber um:

Can't lock /tmp/rsync.lock

E, como esperado, não teremos dois rsync em execução.

No OpenWrt, não temos os /etc/cron.* que usamos no Linux. Sendo assim, temos que usar o bom e velho 'crontab -e'. Para rodar todos os dias 1 AM:

0 1 * * * lock -n /tmp/rsync.lock && { bwlimit=30k --partial --archive --delete --delay-updates --delete-after  /mnt/HD-externo-abc/borg/ roteador-remoto::fulano@gmail.com/; lock -u /tmp/rsync.lock; }

Outra funcionalidade interessante é abortar o processo quando ele demorar muito tempo. Assim você pode manter a rotina apenas durante a madrugada. Todavia, isso só faz sentido se usar a opção "--partial". Bem, a partir deste ponto, a linha do comando vai ficar muito longa, mesmo por um costumas one-liner. É hora de fazer um script:

#!/bin/sh
# Sincroniza repositorio local com remoto
#
RSYNC_TIMEOUT=${1:?Informe o tempo maximo em segundos deste script}; shift
REPO_LOCAL=${1:?Informe o repositorio local}; shift
REPO_REMOTE=${1:?Informe o repositorio remoto}; shift
REPO_LOCK=/tmp/rsync-remote.lock

lock -n "$REPO_LOCK" || {
echo "Falha ao obter lock! Existe um rsync-backup rodando?" >&2
exit 1
}
trap "lock -u '$REPO_LOCK'" EXIT

rsync --archive --partial --delete --delay-updates --delete-after "$@" "$REPO_LOCAL" "$REPO_REMOTE" &
pid_rsync="$!"
(sleep $RSYNC_TIMEOUT; echo "Estouro de tempo ($RSYNC_TIMEOUT segundos)" >&2; kill -TERM $pid_rsync) &
pid_timeout="$!"
# Deveria ser kill -TERM -$pid_timeout... mas com o ash nao fuciona ainda
trap "lock -u '$REPO_LOCK'; kill -TERM $pid_timeout $pid_rsync 2>/dev/null" EXIT
wait $pid_rsync
err=$?
exit $err

Que ficaria na cron assim:

#  Roda todos os dias 1AM por 6 horas (21600 segundos)
0 1 * * * /caminho/para/rsync-backup.sh 21600 /mnt/HD-externo-abc/borg/ roteador-remoto::fulano@gmail.com/

E é isso. Agora você já tem um mecanismo de sincronia dos backups.

Recuperando dados

Primeiro, vamos imaginar o cenário onde você precisa recuperar os dados do repositório remoto. Você deve ter perdido os dados principais e também seu backup local. Nesta situação, é provável que você nem tenha mais o seu computador para recuperar os dados.

A primeira alternativa de recuperação é ir fisicamente onde o backup remoto está e copiar o repositório. O melhor seria primeiro reconstruir seu repositório local e depois recuperar o que você quiser com calma a partir dele.

Se o acesso físico for complicado, você pode simplesmente reconstruir seu repositório local fazendo um rsync inverso, como origem o repositório remoto e destino um caminho local. Vai demorar mas funciona.

Por fim, se precisar apenas de uma ou outra coisa, eu recomendaria testar a montagem remota em cima de rsync, como em fuse-rsync. Não testei mas deve funcionar perfeitamente.

Ah, e não se esqueça que você sempre precisa ter acesso a chave ou a senha usada na criação do repositório. E isso sem depender do próprio backup ;-)

Se pintar uma dúvida, tem sempre o fórum deste blog. Até a próxima.

quinta-feira, 12 de fevereiro de 2015

OpenWRT: Cliente VPN com OpenVPN

Mais um artigo da série sobre o OpenWRT.

No post anterior, apresentei a configuração de um servidor VPN utilizando OpenVPN. Comecei por esta solução de VPN por ser, ao meu ver, a mais simples de ser implementada. Apesar de não nativa em nenhum ambiente, ela possui clientes para quase tudo que você vai precisar (inclusive ambientes mobile). A grande vantagem do OpenVPN é a sua facilidade de implementação. Ele opera como qualquer outro serviço de rede com SSL. Tudo acontece em uma porta única (padrão 1194/udp). Servidor atrás de uma NAT? Só encaminhar a porta. Cliente atrás da NAT? Sem problemas! No pior dos casos, aonde existe conexão com a internet com filtragem, provavelmente o firewall permite conexão direta pela porta do HTTPS(443). Em geral ele nem vai sentir se você usar OpenVPN em uma porta 443/tcp. Ah, também funciona sobre proxy HTTP. Fora isto, não precisa de grandes modificações no sistema operacional para suportar o OpenVPN. Basta ele fornecer um mecanismo de placa de rede virtual do tipo TUN ou TAP que o resto é implementado fora do kernel.

Mas eu não gostei do OpenVPN por que ele precisa de uma CA! Não necessariamente, mas é recomendado e normalmente a melhor solução segura e de longo prazo. Existem outras formas de autenticação para OpenVPN como utilizando usuário/senha ou chave compartilhada. Só não considero as melhores para um caso geral. A primeira, utilizando usuário/senha, evita a necessidade de gerar certificados para os clientes. Contudo, você ainda terá o certificado do servidor, que precisa ser validado pelo cliente (e não validá-lo é sim MUITO PERIGOSO). Isto vai exigir que o cliente ainda tenha o ca.crt na sua configuração. Se você terá que gerenciar uma CA para um certificado do servidor, vai ter que copiar o ca.crt para todos os clientes, então já gera o certificado do cliente também e faz o serviço completo. Já a chave compartilhada pode ser útil se você tem apenas uma conexão VPN e nunca mais terá outro cliente. Se tiver mais de um cliente, não é recomendado. Imagine se alguém, que não devia, tem acesso a esta chave? Ao comprometer a chave em um cliente qualquer, a MESMA chave em todos os demais clientes terá que ser alterada. Nada prático para um ambiente com mais de 3 clientes.

Bem, vamos a tema deste artigo: um cliente OpenVPN em OpenWRT. Primeiro, quando vou usar o OpenVPN como cliente em um roteador? Para ligar um segmento de rede remoto. Isto pode ligar a rede da matriz com a filial da outra cidade ou conectar a rede LAN dos seus pais na sua para facilitar aquele suporte de última hora (recomendo).

Instalação

Os pacotes necessários são iguais um servidor, exceto pela CA (que nem precisaria estar no servidor). A diferença entre um servidor e um cliente é apenas configuração. Por isto, copio do post do servidor OpenVPN:

<CTRL+C>
Na versão Barrier Breaker, existe 3 opções de openvpn:
  • openvpn-nossl (sem criptografia)
  • openvpn-openssl
  • openvpn-polarssl

A primeira é mais enxuta mas não utiliza criptografia, o que normalmente é um requisito de um serviço VPN. Os dois seguintes são equivalentes, variando apenas a implementação de ssl que será utilizada. O polarssl é mais enxuto tanto em funcionalidades como em tamanho. É muito interessante para ambientes com restrição de recursos como o roteador e provavelmente terá tudo que você precisa. Contudo, se você já tem o libopenssl instalado por requisito de outro pacote, não vale a pena instalar o polarssl em paralelo. No meu caso, como tenho outros pacotes que já exigem o openssl, vou instalar o segundo pacote (em destaque).
<CTRL+V>

Configuração

A configuração é no mesmo local, /etc/config/openvpn, só com alguns parâmetros a menos/mais:

config 'openvpn' 'client_vpn'      
         option 'client' '1'
         option 'dev' 'tun'
         option 'resolv_retry' 'infinite'
         option 'nobind' '1'
         option 'persist_key' '1'
         option 'persist_tun' '1'
         option 'comp_lzo' 'no'
         option 'verb' '3'
         option 'remote_cert_tls' 'server'
         option 'enable' '1'
         option 'proto' 'udp'
         option 'ca' '/xxx/ca.crt'
         option 'cert' '/xxx/client.crt'
         option 'key' '/xxx/client.key'
         option 'remote' 'endereco.do.meu.servidor 1194'

As grandes adições na configuração são o "client", indicando que é um cliente, o "remote", informando como chegar no servidor e a troca do certificado e chave, antes do servidor para os do cliente. O ca.crt é o mesmo. Coloquei a referência em /xxx, que não existe, para ficar claro que é um diretório arbitrário. Sugiro que você coloque em /etc/openvpn/ mesmo. Outra opção importante é a "remote_cert_tls server". Isto faz com que o cliente não aceite um servidor se o certificado dele não dizer que ele é um servidor (lembra do build-key-server ao invés do build-key no easy-rsa?). Isto evita que um servidor falso de OpenVPN utilizando um certificado de um cliente, mesmo que válido, não se passe por um servidor legítimo.

É hora de disparar o serviço:

/etc/init.d/openvpn start

Acompanhe pelo logread por possíveis erros. Assim como no servidor VPN, se tudo ocorrer como esperado, neste ponto você terá um novo dispositivo (tun0) no seu roteador. Parabéns, você fez a sua primeira conexão VPN entre um cliente e servidor OpenWRT.

Assim como na configuração do servidor, neste momento, o tun0 não pertence a nenhuma interface do OpenWRT (e consequentemente, a nenhuma zona do firewall). Por padrão, este tráfego será descartado.

Pela interface Luci, adicione uma nova interface (sugestão de nome: vpn) no OpenWRT em Rede/Interfaces. Configure-a para ser não gerenciada e escolha o dispositivo tun0. Nesta mesma interface, você já pode atribuir uma zona do firewall (sugiro o nome vpn). Diferentemente do servidor VPN, a zona vpn no cliente atua como uma WAN (que fornece conectividade aos clientes da LAN) especial e não como outra LAN (de onde vem as conexões dos clientes). Por este motivo, a configuração é distinta. Você vai querer habilitar o encaminhamento de pacotes entre a zona vpn e a lan. Se optar por mascarar a rede (NAT), não vai precisar de configurações extras. Se não existir colisões de rede e você quiser acessar diretamente os clientes, explico mais adiante. Para ambiente corporativo, pode ser interessante retirar o encaminhamento padrão da lan para a wan. Isto evita o acesso dos clientes da LAN à internet pela WAN. Caso eles necessitem de acesso internet, terão que passar pela VPN e sair pela conexão internet da rede do servidor VPN.

Configuração com um "plus a mais"

Para não utilizar o mascaramento da rede LAN de um cliente VPN, você precisa informar ao servidor OpenVPN que existe a rede 10.4.3.0/24 atrás do cliente de VPN client-filial1. Isto fará com que o OpenVPN adicione rotas locais que encaminham os pacotes para a rede 10.4.3.0/24 ao endereço IP em uso atualmente pelo cliente client-filial1. Vamos precisar alterar a configuração do servidor VPN.

No servidor VPN (em /etc/config/openvpn), adicione o "client_config_dir" uma única vez e uma rota para cada subrede de clientes VPN:

/etc/config/openvpn:
       option 'client_config_dir' '/etc/openvpn/ccd'
       list 'route' '192.168.4.0 255.255.255.0'
       list 'route' '192.168.5.0 255.255.255.0'
       ...

O "route" adiciona a rota ao sistema do servidor para enviar pacotes de cada uma das respectivas redes ao OpenVPN. Se um cliente possuir mais de uma rede ou existir mais de um cliente com subredes, adicione novas linhas. OK, mas com o OpenVPN sabe para qual cliente ele deve enviar? Ai entra o client_config_dir. Neste diretório existirão arquivos individuais que acrescentam configurações específicas para cada cliente. Na sugestão, os arquivos ficam em /etc/openvpn/ccd/xxx, onde xxx é o nome do CN informado na geração do certificado no comando build-key (não o nome do arquivo!). Se não lembrar o que você digitou, pode resgatar esta informação com este comando sobre o arquivo .crt do cliente:


# openssl x509 -in /etc/easy-rsa/keys/client1.crt -text | grep Subject: 
Subject: C=BR, ST=XX, ... CN=client-abc/name=EasyRSA/emailAddress=abc@abc.com

No caso, seria o cliente-abc e você precisaria criar o arquivo em /etc/openvpn/ccd/cliente-abc no servidor VPNNeste arquivo, adicione as rotas para as LANs alcançáveis através deste cliente VPN:

/etc/openvpn/ccd/cliente-abc:
iroute 192.168.4.0 255.255.255.0

Lembrando que a rede no iroute é a mesma que também está presente na configuração do servidor VPN (mas neste caso é iroute mesmo e não route).

Feito! Agora você já pode acessar o computador da sua mãe para achar onde ela salvou aquele arquivo importante sem precisar de voltas mirabolantes, encaminhamentos de porta ou soluções para atravessar a NAT. Basta acessar o computador como se fosse um outro computador da sua rede.

No próximo post, vou tentar preparar um artigo sobre VPN utilizando IPsec. É um tanto mais complicado e bem mais entrelaçado aos recursos do sistema operacional. IPsec é implementado no kernel e os programas auxiliares cuidam apenas da parte burocrática como negociar as chaves, configurar rotas e informar o kernel dos parâmetros do IPsec.

Alguma dúvida? Criei um fórum para o blog e com um tópico para cada novo artigo. Até a próxima.