Discuta este tópico no fórum

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

terça-feira, 17 de abril de 2018

OpenWrt: Configurando IPv6 (6 anos depois)

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

O que motivou iniciar o uso do OpenWrt não foi os inúmeros recursos a mais que você pode fazer com ele. O real motivador foi que eu queria usar IPv6 na minha rede. Escrevi sobre isso em 2012. Acho que cabe retomar o assunto.

Na época, o IPv6 no OpenWrt era opcional. As operadoras entregarem IPv6 era lenda urbana, quando não queriam te "vender" o pacote extra IPv6. O acesso IPv6 era coisa de universidade. A única alternativa era criar um túnel (lento) para um broker IPv6. De lá para cá, muita coisa mudou.

Hoje, todas as operadoras que se consideram minimamente significativas oferecem IPv6 a seus clientes. Então, se você não tem IPv6, já sabe o nível da sua operadora. As operadoras já estão com falta de IPv4 faz um tempo, tendo que apelar para técnicas como CGN (NAT na operadora) que, basicamente, coloca uma NAT na frente da sua NAT. O problema é que a sua NAT você tinha um certo nível de controle, podendo abrir/encaminhar portas. Já a NAT da operadora... Isso quebra um monte de coisas que iriam conectar na sua casa (ex: torrent, VPN, Câmera IP...). Se sua operadora tem que usar CGN, mas ao menos entrega IPv6, é a vida. Procure migrar suas coisas para IPv6. Se ela usa CGN mas não entrega IPv6... ela é incompetente. Procure trocar de operadora.

No mundo do OpenWrt, o IPv6 melhorou muito. Hoje em dia, ele vem autoconfigurado para IPv6. O normal é ele funcionando tão bem quanto IPv4, sem a necessidade de qualquer configuração. Não precisa de pacotes extras, ele simplesmente sai funcionando.

Vamos a um básico IPv6. Primeiro, o endereço. O IPv4 usava 32-bit, que dava um pouco mais de 4 bilhões de endereços (2^32). Deste tanto, tinha que tirar algumas faixas reservadas, um tanto para equipamentos intermediários, endereço de rede, broadcast. No fim, temos endereços para bem menos do que 4 bilhões de equipamentos. E com 7 bilhões de pessoas no planeta, isso era insuficiente. No IPv6, o pessoal exagerou e resolveu aumentar de 32-bit para 128-bit. Fica um trambolho deste tamanho:

2001:db8:85a3:8d3:1319:8a2e:370:7348

Cada conjunto separado por ":" tem 16-bit, ou 65536 variações. Com dois destes poderíamos colocar a internet IPv4 inteira (e temos 8 aqui). Como os números começaram a ficar grandes, resolveram usar notação hexadecimal, que inclui os algarismos normais e as letras de A até F. Isto permite usar endereços legíveis engraçadinhos. Caso tenha uma sequência de zeros, usa-se a notação "::", mas somente uma vez no endereço.

Existem variações para endereços especiais, como multicast, link-local, mas no caso geral, o endereço IPv6 pode ser dividido em duas partes, cada uma com 64-bit. No exemplo anterior, seriam as partes verdes e azul. A verde é seu prefixo de rede, que identifica uma rede IPv6 no mundo. A parte azul é o identificador da interface. Para fazer a analogia com  algo que todos têm familiaridade, seria algo assim no IPv4 privado da sua rede atual:

192.168.3.131/24

Então, com IPv4 você normalmente trabalha com redes /24 com 254 endereços "livres". Com IPv6, no mínimo temos 18.446.744.073.709.551.616 (2^64). Para quê tudo isso? Bem, assim você pode usar o endereço MAC da sua placa (48-bit) e obter automaticamente um endereço sem chance de conflito. Esse é o método de obtenção de endereços sem estado (SLAAC). Funciona assim:

equipamento: olá! tem um roteador aí? Eu preciso de uma rede!
roteador: Oi, eu sou o roteador no endereço fe80::1234:1234:3214:1234. Eu ofereço o prefixo de rede 2001:db8:85a3:8d3::/64

E o equipamento começa a usar 2001:db8:85a3:8d3:1319:8a2e:370:7348 usando fe80::1234:1234:3214:1234 como roteador padrão. Sem mais nenhum passo. Sem nenhuma negociação ou confirmação.

Este endereço, apesar de parecer "aleatório", será sempre igual, claro, se mantido o prefixo de rede. Equipamentos mais simples (IoT) podem só funcionar desta forma. E o DNS? Esse pode vir pelo serviço RDNSS, que vem junto com a resposta do roteador. Mas nem todos os clientes e roteadores suportam isso.

E não tem DHCPv6? Tem sim. Ele funciona de uma forma bem parecida com DHCPv4, mas pode tanto gerar os endereços dos clientes da mesma forma que o SLAAC ou da forma tradicional do IPv4: alocando de uma faixa de endereços (que podem ser fixados).

O prefixo de rede ainda pode ser dividido em duas partes: prefixo de roteamento e um identificador de subrede. O prefixo de roteamento é o que identifica todas as redes gerenciadas pelo seu roteador. Então, qualquer rede "acessível globalmente" no seu roteador compartilha essa parte inicial. O que sobra até atingir os 64-bit é usado pelo seu roteador para subdividir a rede em múltiplas redes locais. 

Vamos ao OpenWrt.

Ao ligar o OpenWrt, ele cria aleatoriamente um endereço de rede local (ULA). Sim, o recomendado é ser aleatório mesmo. Esse endereço é um /48 e sempre começa com "fd". Ex:

fdab:1234:1343::/48

Você pode ver (ou modificar) este endereço na aba "network/interfaces", lá no final. Isto seria equivalente a sua rede privada 192.168.1.0/24 do IPv4. Diferentemente do IPv4, eu não recomendo que mude este valor. 

O OpenWrt usa o "prefixo de roteamento" fdab:1234:1343:: e adiciona um identificador de subrede para formar uma rede final, normalmente de tamanho /64, mas pode ser modificado pela opção "ip6assign". E de onde ele pega identificador de subrede? Do campo "ip6hint". Se não definido, ele usa zero. Para o endereço anterior, ficaria:

fdab:1234:1343::/64

Mas é igual? Não! Agora tem um monte de zeros até chegar ao /64. De 48 para 64 são 16-bit ou 4 algarismos/letras em hexadecimal. Seria igual a isso:

fdab:1234:1343:0000::/64

Onde o magenta é o identificador da subrede. Se ele fosse "12", o resultado seria:

fdab:1234:1343:0012::/64

Simples? Por enquanto estamos só na rede local. O DHCPv6 pode ser configurado no mesmo local onde era configurado o IPv4, ao final da edição de cada interface. Lá você pode configurar se o roteador se anunciará como roteador (para SLAAC), se terá DHCPv6 e qual modo de endereços será distribuído pelo DHCPv6: SLAAC, por atribuição ou ambos. 

E como ficariam os endereços de rede? O OpenWrt normalmente usa o identificador de rede ::1 para si. Então, na subrede fdab:1234:1343:123A::/64, ele ficaria com:

fdab:1234:1343:0012::1/64

Mas o "::1" pode ser modificado pelo campo ip6ifaceid. E uma máquina na rede? Se ela tiver o endereço MAC 11:22:33:44:55:66, por SLAAC ela teria o endereço:

fdab:1234:1343:0012:1322:33ff:fe44:5566/64

Note que o MAC sofre uma pequena alteração, mas ele é visível no endereço. E se for por atribuição DHCPv6, será dinâmico (com relativa estabilidade) como no DHCPv4. E se eu quiser fixar? Assim como a interface tem o atributo "ip6ifaceid", a entrada DHCP onde você fixa o IPv4 terá um campo "hostid" (na interface WEB está como "IPv6-Suffix") onde você pode preencher o que quiser lá (até 64-bit ou 16 algarismos hexadecimais). Se for "cafe", o endereço ficaria:

fdab:1234:1343:0012::cafe/64

Pronto. Temos uma rede local que fala IPv6. Isto vai estar disponível em qualquer OpenWrt recente, mesmo que sua operadora não ofereça IPv6. Os endereços fd00::/8 não são (normalmente) roteáveis para a internet. Só devem ser usados dentro da sua rede doméstica ou corporativa.

Agora vamos falar com a Internet.

O básico de um roteador é ter uma interface WAN e uma ou mais LAN. Normalmente o endereço WAN IPv6 é obtido por DHCPv6 (ex: NetVirtua) ou por PPPoE/PPPoA (ex: Oi). Como é um protocolo diferente do IPv4, no OpenWrt é necessário usar uma segunda interface (ex: wan6) que utiliza o mesmo dispositivo físico da wan IPv4. Por padrão, ele já vem com uma wan6 configurada como DHCPv6, que resolve em grande parte dos casos.

O que muda do DHCPv4? Na requisição do DHCPv6, além de pedir um endereço para a interface WAN, existe um pedido de um campo adicional chamado de "prefixo de rede delegada" (Prefix Delegated - PD).  Você receberá da sua operadora um endereço WAN para seu roteador e um prefixo de rede com endereços reais (globais) para distribuir dentro da sua rede. O tamanho do prefixo solicitado pode ser modificado pelo campo "reqprefix", mas as operadoras não vão respeitar mesmo. Você receberá algo como:

IPv6 WAN: 2804:14d:baba:1000::17d7/64
IPv6 prefixo delegado: 2804:14d:baba:1f00::/56

Se a WAN IPv6 utilizar endereço IP fixo, você pode informar a rede delegada manualmente.

O que o OpenWrt faz com isso? O IPv6 WAN é usado para a interface WAN. Ele pode ser, inclusive um /128. Já o prefixo delegado é distribuído para todas as LANs internas. Da mesma forma que ocorreu com a  rede ULA, ele utilizará o prefixo roteado em conjunto com o identificador da subrede para criar prefixos de rede para cada rede interna. No exemplo, a operadora ofereceu um prefixo /56 (ex: Oi ADSL residencial), que permitiria subdividi-lo em 256 redes. É o suficiente para uma residência ou mesmo para um pequeno negócio.

( Bem, tem algumas operadoras que entregam apenas um /64 para seus clientes. Sim NetVirtua, estou apontando para você. Pode ser trauma da escassez de IPv4 mas não se justifica no mundo IPv6. Até a Oi, que normalmente não é usada como bom exemplo, oferece uma rede /56. Com uma rede /64, eu não tenho espaço para subdividir a rede em múltiplas redes LAN e ainda usar SLAAC. Isto quer dizer que não tenho como criar uma segunda LAN com IPv6. Mas quem precisa de duas LAN? Isso é coisa de empresa! Claro, o vizinho que eventualmente fez uma visita e precisou conectar na Wifi aqui em casa jamais irá enviar um vídeo por engano ao meu Chromecast, nem mesmo irá olhar sem querer na babá eletrônica... realmente a segunda rede é desnecessária. Não preciso dizer qual foi a resposta do Call Center da Net. Mas voltando... )

Com as redes do exemplo, a LAN do roteador passa a ter estes dois endereços:

fdab:1234:1343:0012::1/64
2804:14d:baba:1f12::1/64

E a máquina que tem o endereço MAC 11:22:33:44:55:66? Se usar tanto o SLAAC como o sufixo "cafe", teremos todos estes endereços configurados:

fd
ab:1234:1343:0012:1322:33ff:fe44:5566/64
fdab:1234:1343:0012::cafe/64
2804:14d:baba:1f12:1322:33ff:fe44:5566/64
2804:14d:baba:1f12::cafe/64

E para cada outra LAN no roteador, basta configurar o campo ip6hint dela com um identificador diferente das demais LAN e ela receberá seu cunhão de endereços automaticamente.

E se não tiver espaço para uma segunda LAN? O que posso fazer? E se minha operadora não entregar um prefixo delegado? Infelizmente, ainda temos a alternativa de usar NAT66 (NAT entre duas redes IPv6).

Beleza. Acabei de olhar a interface do meu computador e tem esses quatro endereços aí e mais um monte! Sim, temos ainda endereços usados apenas no contexto do enlace local (link-local), que começam com "fe80". Ele seria equivalente ao famigerado 169.254.0.0/24 do IPv4.

fe80::1322:33ff:fe44:5566/64

Este endereço normalmente nem responde aos serviços de rede normais. Ele é usado para as tarefas administrativas do IPv6, como encontrar um outro equipamento na mesma rede ou o seu roteador. É necessário.

Mas tenho muito mais endereços! Bem, o endereço MAC não é algo muito "mutável" nas máquinas. Como ele começou a fazer parte do endereço visível na internet, ficou fácil rastrear os equipamentos que usam SLAAC. Mesmo que você mude o prefixo, o final sempre será o mesmo. Com isso você obtem o MAC e individualiza o computador. Solução? Uma extensão de privacidade. Além de todos os endereços listados anteriormente, a máquina pode periodicamente criar novos endereços com o identificador de interface (parte verde) aleatória. Quando usada a extensão de privacidade, o endereço SLAAC fixo é usado para receber conexões que queiram se conectar no computador enquanto os endereços aleatórios são usados pelo computador para acessar serviços remotos. Depois de um tempo, o endereço aleatório é desativado e outro é criado. Com isso, o serviço remoto não tem como rastrear o equipamento apenas pelo endereço de origem. Se deixar um computador que usa a extensão de privacidade muito tempo ligado, é normal ver uma lista mais de uma dezena de endereços IPv6.

E tem mais assuntos IPv6? Tem! Firewall IPv6, NAT66 (sim, NAT para IPv6 as vezes é necessário), multihoming (duas WANs), VPN sobre IPv6, e assim por diante. Mas isso fica para outro artigo.

Se pintar uma dúvida, temos o fórum.

Até a próxima.

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.