
Automático, seguro, distribuído, com conexões transitivas (ou seja, encaminhando mensagens quando não há acesso direto entre assinantes), sem um único ponto de falha, rede VPN de ponto a ponto, testada pelo tempo, baixo consumo de recursos e malha completa com a capacidade de "perfurar" NAT - é possível?
As respostas corretas são:
- sim, com dor se você usar tinc.
- sim, fácil se você usar tinc + tinc-boot
Skip Link Introdutório
Descrição Tinc
Infelizmente, poucas informações foram publicadas sobre o Tinc VPN no Habré, mas ainda há alguns artigos relevantes:
Os artigos em inglês podem ser distinguidos:
A fonte original é melhor considerar a documentação original do Tinc man
Portanto, (uma reimpressão gratuita do site oficial), o Tinc VPN é um serviço (daemon tincd
) que garante o funcionamento de uma rede privada, encapsulando e criptografando o tráfego entre os nós. O código fonte está aberto e disponível sob a licença GPL2. Como a solução clássica (OpenVPN), a rede virtual criada está disponível no nível IP (OSI 3), o que significa que, no caso geral, não é necessário fazer alterações nos aplicativos.
Principais recursos:
- criptografia, autenticação e compactação de tráfego;
- solução de malha completa totalmente automática, que inclui a construção de conexões com os nós da rede no modo tudo com todos ou, se isso não for aplicável, o encaminhamento de mensagens entre hosts intermediários;
- soco NAT;
- a capacidade de conectar redes isoladas no nível da Ethernet (comutador virtual);
- suporte a vários sistemas operacionais: Linux, FreeBSD, OS X, Solaris, Windows, etc.
Existem dois ramos do desenvolvimento do tinc: 1.0.x (em quase todos os repositórios) e 1.1 (beta eterno). O artigo usa a versão 1.0.x em qualquer lugar.
O Tinc 1.1x fornece vários novos recursos principais: segurança avançada perfeita, conectividade simplificada do cliente (na verdade, substituindo o tinc-boot
) e um design geralmente mais cuidadoso.
No entanto, no momento, uma versão estável - 1.0.x é indicada e destacada no site oficial; portanto, ao usar todas as vantagens da ramificação 1.1, você deve avaliar todas as vantagens e desvantagens de usar uma versão não final.
Do meu ponto de vista, uma das possibilidades mais fortes é encaminhar mensagens quando a conexão direta não é possível. Ao mesmo tempo, as tabelas de roteamento são criadas automaticamente. Até nós sem um endereço público podem passar o tráfego por si mesmos.

Considere a situação com três servidores (China, Rússia, Cingapura) e três clientes (Rússia, China e Filipinas):
- servidores têm um endereço público, clientes por trás do NAT;
- ILV durante a próxima proibição de prováveis proxies O Telegram bloqueou todos os hosters, exceto a China "amiga";
- a fronteira da rede da China <-> RF é instável e pode cair (devido ao ILV e / ou devido ao censor chinês);
- as conexões com Cingapura são condicionalmente estáveis (experiência pessoal);
- Manila (Filipinas) não é uma ameaça para ninguém e, portanto, é permitida para todos (devido à distância de todos e de tudo).
Por exemplo, na troca de tráfego entre Xangai e Moscou, considere os cenários de Tinc (aproximadamente):
- Situação nativa: Moscou <-> russia-srv <-> china-srv <-> Xangai
- ILV fechou a conexão com a China: Moscou <-> russia-srv <-> Manila <-> Cingapura <-> Xangai
- (após 2) em caso de falha do servidor em Cingapura, o tráfego é transferido para o servidor na China e vice-versa.
Sempre que possível, o Tinc tenta estabelecer uma conexão direta entre os dois nós por trás do NAT perfurando.
Uma breve introdução à configuração do tinc
Tinc está posicionado como um serviço fácil de configurar. No entanto, algo deu errado - para criar um novo nó, é minimamente necessário:
- Descreva a configuração do host (tipo, nome) (
tinc.conf
); - Descreva o arquivo de configuração (sub-redes atendidas, endereços públicos) (
hosts/
); - crie uma chave;
- crie um script especificando o endereço do nó e os parâmetros relacionados (
tinc-up
); - é aconselhável criar um script que apague os parâmetros criados depois de parar (
tinc-down
).
Além disso, ao conectar-se a uma rede existente, você deve obter as chaves do host existentes e fornecer as suas próprias.
Ou seja: para o segundo nó

Para o terceiro

Ao usar a sincronização bidirecional (por exemplo, unison
), o número de operações adicionais aumenta para N partes, onde N é o número de nós públicos.
Devemos prestar homenagem aos desenvolvedores do Tinc - para inclusão na rede, basta trocar chaves
com apenas um dos nós (nó de inicialização). Após iniciar o serviço e conectar-se ao participante, o tinc obterá a topologia
rede e poderá trabalhar com todos os assinantes.
No entanto , se o host de inicialização ficar indisponível e o tinc for reiniciado, não haverá como
irá se conectar à rede virtual.
Além disso, as enormes possibilidades de tinc, juntamente com a documentação acadêmica disso (bem descrita, mas com poucos exemplos), fornecem um campo extenso para erros.
Razões para criar tinc-boot
Se generalizarmos os problemas descritos acima e os formularmos como tarefas, obteremos:
- é necessária a capacidade de criar um novo site com o mínimo esforço;
- potencialmente, é necessário possibilitar que o especialista médio (enikey) tenha uma pequena linha para criar um novo nó e conectar-se à rede;
- é necessário fornecer distribuição automática de chaves entre todos os nós ativos;
- é necessário fornecer um procedimento simplificado de troca de chaves entre o bootnod e o novo cliente.
bootnode - um nó com um endereço público (veja acima);
Devido aos requisitos da reivindicação 2, pode-se argumentar que após a troca de chaves entre o nó de inicialização e o novo nó e após
Ao conectar o nó à rede, a distribuição da nova chave ocorrerá automaticamente.
São essas tarefas que o tinc-boot executa.
O tinc-boot é um aplicativo de código aberto independente, além do tinc
, que fornece:
- criação simples de um novo nó;
- conexão automática a uma rede existente;
- definir a maioria dos parâmetros por padrão;
- distribuição de chaves para nós de mel.
Arquitetura
O arquivo executável tinc-boot
consiste em quatro componentes: um servidor de nó de inicialização, um servidor de gerenciamento de distribuição de chaves e comandos de gerenciamento de RPC para ele, além de um módulo de geração de nós.
Módulo de geração de nós
O módulo de geração de nós ( tinc-boot gen
) cria todos os arquivos necessários para que o tinc seja executado com êxito.
Simplificado, seu algoritmo pode ser descrito da seguinte forma:
- Defina o nome do host, rede, parâmetros IP, porta, máscara de sub-rede, etc.
- Normalize-os (o tinc tem um limite em alguns valores) e crie os que estão faltando
- Verifique os parâmetros
- Se necessário, instale o tinc-boot no sistema (desativável)
- Criar
subnet-down
tinc-up
, tinc-down
, subnet-up
subnet-down
, subnet-down
- Crie o
tinc.conf
configuração tinc.conf
- Criar
hosts/
- Executar geração de chaves
- Executar troca de chaves com o nó de inicialização
- Criptografe e assine seu próprio arquivo do host com uma chave pública, um vetor de inicialização aleatória (nounce) e nome do host usando xchacha20poly1305, em que a chave de criptografia é o resultado da função sha256 do token
- Enviar dados via protocolo HTTP para o nó de inicialização
- Decifre a resposta recebida e o cabeçalho do
X-Node
contém o nome do nó de inicialização usando o nounce original e o mesmo algoritmo - Se for bem-sucedido, salve a chave recebida nos
hosts/
e adicione uma entrada ConnectTo
ao arquivo de configuração (ou seja, uma recomendação onde se conectar) - Caso contrário, use o seguinte endereço na lista do nó de inicialização e repita da etapa 2
- Mostrar recomendações sobre como iniciar um serviço
A conversão via SHA-256 é usada apenas para normalizar a chave para 32 bytes
Para o primeiro nó (ou seja, quando não há nada a especificar como o endereço de inicialização), a etapa 9 é ignorada. Bandeira - --standalone
.
Exemplo 1 - criando o primeiro site público
O endereço público é 1.2.3.4
sudo tinc-boot gen --standalone -a 1.2.3.4
- o sinalizador
-a
permite especificar endereços disponíveis ao público
Exemplo 1 - adicionando um nó não público à rede
O nó de inicialização será retirado do exemplo acima. O host deve ter o nó de inicialização tinc-boot em execução (descrito posteriormente).
sudo tinc-boot gen --token "MY TOKEN" http://1.2.3.4:8655
- o sinalizador
--token
define o token de autorização
Módulo de inicialização
O tinc-boot bootnode
gera um servidor HTTP com uma API para troca de chave primária com novos clientes.
Por padrão, a porta 8655
.
Simplificado, o algoritmo pode ser descrito da seguinte maneira:
- Aceitar uma solicitação de um cliente
- Descriptografe e verifique a solicitação usando xchacha20poly1305, usando o vetor de inicialização passado durante a solicitação e onde a chave de criptografia é o resultado da função sha256 do token
- Verificar nome
- Salvar arquivo se ainda não houver um arquivo com o mesmo nome
- Criptografe e assine seu próprio arquivo e nome de host usando o algoritmo descrito acima
- Voltar ao item 1
Juntos, o processo de troca de chaves primárias é o seguinte:

Exemplo 1 - iniciando o nó de download
Supõe-se que a inicialização inicial do nó foi realizada ( tinc-boot gen
)
tinc-boot bootnode --token "MY TOKEN"
- o sinalizador
--token
define o token de autorização. Deve ser o mesmo para clientes que se conectam ao host.
Exemplo 2 - iniciando o nó de download como um serviço
tinc-boot bootnode --service --token "MY TOKEN"
- o sinalizador
--service
a criar um serviço systemd (por padrão, neste exemplo, tinc-boot-dnet.service
) - o sinalizador
--token
define o token de autorização. Deve ser o mesmo para clientes que se conectam ao host.
Módulo de distribuição de chaves
O módulo de distribuição de chaves ( tinc-boot monitor
) gera um servidor HTTP com uma API para trocar chaves com outros nós dentro da VPN . É fixado no endereço emitido pela rede (a porta padrão é 1655
, não haverá conflitos com várias redes, pois cada rede possui / deve ter seu próprio endereço).
O módulo inicia e funciona completamente automaticamente: você não precisa trabalhar com ele no modo manual.
Este módulo inicia automaticamente quando a rede está tinc-up
(no script tinc-down
) e para automaticamente quando pára (no script tinc-down
).
Suporta operações:
GET /
- fornece seu arquivo de nóPOST /rpc/watch?node=<>&subnet=<>
- escolhe um arquivo de outro nó, assumindo que exista um serviço semelhante em execução nele. Por padrão, as tentativas atingem o tempo limite de 10 segundos, a cada 30 segundos até o sucesso ou cancelamento.POST /rpc/forget?node=<>
- deixa tentativas (se houver) de pegar o arquivo em outro nóPOST /rpc/kill
- finaliza o serviço
Além disso, a cada minuto (por padrão) e quando um novo arquivo de configuração é recebido, a indexação dos nós salvos é feita para novos nós públicos. Quando nós com o sinalizador Address
são detectados, uma entrada é adicionada ao arquivo de configuração tinc.conf
para recomendar a conexão ao reiniciar.
Módulo de Distribuição de Chaves (Gerenciamento)
Os comandos para solicitar ( tinc-boot watch
) e cancelar a solicitação ( tinc-boot forget
) do arquivo de configuração de outros nós são executados automaticamente quando um novo nó é detectado (script de subnet-up
) e parado (script de subnet-down
), respectivamente.
No processo de parada do serviço, o script tinc-down
é tinc-down
no qual o comando tinc-boot kill
interrompe o módulo de distribuição de chaves.
Em vez de total
Esse utilitário foi criado sob a influência da dissonância cognitiva entre o gênio dos desenvolvedores de Tinc e a complexidade linear crescente da criação de novos nós.
As principais idéias no processo de desenvolvimento foram:
- se algo pode ser automatizado, deve ser automatizado;
- os valores padrão devem cobrir pelo menos 80% de uso (princípio de Pareto);
- qualquer valor pode ser redefinido usando sinalizadores e variáveis de ambiente;
- a utilidade deve ajudar, e não causar um desejo de invocar todo o castigo do céu ao criador;
- o uso de um token de autorização para a inicialização é um risco óbvio; no entanto, na medida do possível, ele foi minimizado devido à criptografia e autenticação totais (mesmo o nome do host no cabeçalho da resposta não pode ser substituído).
Um pouco de cronologia:
- A primeira vez que usei tinc há mais de 4 anos. Estudou uma quantidade significativa de material. Configure uma rede ideal (na minha opinião)
- Após meio ano, o tinc foi substituído por zerotier, como uma ferramenta mais conveniente / flexível
- 2 anos atrás, eu fiz um manual ansible para implantar tinc
- Um mês depois, meu script foi interrompido na implantação incremental (ou seja, quando é impossível acessar todos os nós da rede, o que significa distribuir chaves)
- Há duas semanas, escrevi um script bash-script que era o protótipo do
tinc-boot
- 3 dias atrás após a segunda iteração, nasceu a primeira versão (0.0.1 para ser exato) do utilitário
- Há um dia, reduzi a instalação de um novo nó para uma linha:
curl -L https://github.com/reddec/tinc-boot/releases/latest/download/tinc-boot_linux_amd64.tar.gz | sudo tar -xz -C /usr/local/bin/ tinc-boot
curl -L https://github.com/reddec/tinc-boot/releases/latest/download/tinc-boot_linux_amd64.tar.gz | sudo tar -xz -C /usr/local/bin/ tinc-boot
- Em breve, será adicionada a possibilidade de uma conexão ainda mais simples à rede (sem sacrificar a segurança)
Durante o desenvolvimento, testei ativamente em servidores e clientes reais (a imagem da descrição do tinc acima foi tirada da vida real). Agora, o sistema funciona perfeitamente e todos os serviços VPN de terceiros agora estão desativados.
O código do aplicativo está escrito no GO e está aberto sob a licença MPL 2.0. Uma licença (tradução livre) permite o uso comercial (se alguém precisar de repente) sem abrir o produto de origem. O único requisito é que as alterações sejam transferidas para o projeto.
Pedidos de piscina são bem-vindos.
Links úteis