Migração de OpenVPN para WireGuard para consolidar redes em uma rede L2

Migração de OpenVPN para WireGuard para consolidar redes em uma rede L2

Gostaria de compartilhar minha experiência de combinar redes em três apartamentos geograficamente distantes, cada um dos quais usa roteadores com OpenWRT como gateway, em uma rede comum. Ao escolher um método para combinar redes entre L3 com roteamento de sub-rede e L2 com bridging, quando todos os nós da rede estarão na mesma sub-rede, foi dada preferência ao segundo método, que é mais difícil de configurar, mas oferece mais oportunidades, pois transparente o uso de tecnologias foi planejado na rede criada Wake-on-Lan e DLNA.

Parte 1: Histórico

O OpenVPN foi inicialmente escolhido como o protocolo para implementar esta tarefa, pois, em primeiro lugar, pode criar um dispositivo de toque que pode ser adicionado à ponte sem problemas e, em segundo lugar, o OpenVPN suporta a operação sobre o protocolo TCP, o que também foi importante, porque nenhum dos apartamentos tinha um endereço IP dedicado e não consegui usar o STUN, porque por algum motivo meu ISP bloqueia as conexões UDP de entrada de suas redes, enquanto o protocolo TCP me permitiu encaminhar a porta do servidor VPN no VPS alugado usando SSH. Sim, essa abordagem dá uma grande carga, pois os dados são criptografados duas vezes, mas não queria introduzir o VPS na minha rede privada, pois ainda havia o risco de terceiros obterem controle sobre ela, portanto, ter tal dispositivo na rede doméstica era extremamente indesejável e foi decidido pagar pela segurança com uma grande sobrecarga.

Para encaminhar a porta no roteador no qual foi planejado implantar o servidor, foi utilizado o programa sshtunnel. Não vou descrever os meandros de sua configuração - isso é feito com bastante facilidade, apenas observo que sua tarefa era encaminhar a porta TCP 1194 do roteador para o VPS. Em seguida, o servidor OpenVPN foi configurado no dispositivo tap0, que foi conectado à ponte br-lan. Depois de verificar a conexão com o servidor recém-criado do laptop, ficou claro que a ideia do encaminhamento de porta se justificava e meu laptop tornou-se membro da rede do roteador, embora não estivesse fisicamente nele.

O assunto permaneceu pequeno: era necessário distribuir endereços IP em diferentes apartamentos para que não entrassem em conflito e configurar roteadores como clientes OpenVPN.
Os seguintes endereços IP do roteador e intervalos de servidores DHCP foram selecionados:

  • 192.168.10.1 com alcance 192.168.10.2 - 192.168.10.80 para o servidor
  • 192.168.10.100 com alcance 192.168.10.101 - 192.168.10.149 para um roteador no apartamento nº 2
  • 192.168.10.150 com alcance 192.168.10.151 - 192.168.10.199 para um roteador no apartamento nº 3

Também foi necessário atribuir exatamente esses endereços aos roteadores clientes do servidor OpenVPN adicionando a linha à sua configuração:

ifconfig-pool-persist /etc/openvpn/ipp.txt 0

e adicionando as seguintes linhas ao arquivo /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

onde flat1_id e flat2_id são os nomes dos dispositivos especificados ao gerar certificados para conectar-se ao OpenVPN

Em seguida, os clientes OpenVPN foram configurados nos roteadores, os dispositivos tap0 em ambos foram adicionados à ponte br-lan. Nesta fase, tudo parecia estar em ordem, pois as três redes se veem e funcionam como um todo. No entanto, surgiu um detalhe não muito agradável: às vezes os dispositivos podiam obter um endereço IP não de seu roteador, com todas as consequências daí decorrentes. Por algum motivo, o roteador de um dos apartamentos não teve tempo de responder ao DHCPDISCOVER a tempo e o dispositivo recebeu o endereço errado. Percebi que preciso filtrar essas solicitações em tap0 em cada um dos roteadores, mas, como descobri, o iptables não pode funcionar com um dispositivo se ele fizer parte de uma ponte e o ebtables deve vir em meu auxílio. Para meu pesar, não estava no meu firmware e tive que reconstruir as imagens de cada aparelho. Fazendo isso e adicionando essas linhas ao /etc/rc.local de cada roteador, o problema foi resolvido:

ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP

Essa configuração durou três anos.

Parte 2: Apresentando o WireGuard

Recentemente, a Internet tem falado cada vez mais sobre o WireGuard, admirando a simplicidade de sua configuração, alta velocidade de transferência, ping baixo com segurança comparável. A busca por mais informações sobre ele deixou claro que nem o trabalho como membro da ponte nem o trabalho sobre o protocolo TCP são suportados por ele, o que me fez pensar que ainda não há alternativas ao OpenVPN para mim. Então adiei para conhecer o WireGuard.

Há alguns dias, espalhou-se por meio de recursos de uma forma ou de outra relacionados à TI que o WireGuard finalmente será incluído no kernel do Linux, a partir da versão 5.6. Artigos de notícias, como sempre, elogiaram o WireGuard. Novamente mergulhei na busca de maneiras de substituir o bom e velho OpenVPN. Desta vez eu me deparei Este artigo. Ele falou sobre a criação de um túnel Ethernet sobre L3 usando GRE. Este artigo me deu esperança. Não ficou claro o que fazer com o protocolo UDP. A pesquisa me levou a artigos sobre o uso do socat em conjunto com um túnel SSH para encaminhar uma porta UDP; no entanto, eles observaram que essa abordagem funciona apenas no modo de conexão única, o que significa que vários clientes VPN seriam impossíveis. Tive a ideia de configurar um servidor VPN em um VPS e configurar o GRE para clientes, mas descobri que o GRE não suporta criptografia, o que levará ao fato de que, se terceiros obtiverem acesso ao servidor , todo o tráfego entre minhas redes está nas mãos deles, o que não me convinha.

Novamente, a decisão foi tomada em favor da criptografia redundante, usando VPN sobre VPN de acordo com o seguinte esquema:

VPN de Camada XNUMX:
VPS é servidor com endereço interno 192.168.30.1
MS é pelo cliente VPS com endereço interno 192.168.30.2
MK2 é pelo cliente VPS com endereço interno 192.168.30.3
MK3 é pelo cliente VPS com endereço interno 192.168.30.4

VPN de Camada XNUMX:
MS é servidor com endereço externo 192.168.30.2 e interno 192.168.31.1
MK2 é pelo cliente MS com o endereço 192.168.30.2 e tem um IP interno de 192.168.31.2
MK3 é pelo cliente MS com o endereço 192.168.30.2 e tem um IP interno de 192.168.31.3

* MS - roteador-servidor no apartamento 1, MK2 - roteador no apartamento 2, MK3 - roteador no apartamento 3
* As configurações do dispositivo estão publicadas no spoiler ao final do artigo.

E assim, pings entre os nós da rede 192.168.31.0/24 vão, é hora de passar para a configuração do túnel GRE. Antes disso, para não perder o acesso aos roteadores, vale a pena configurar túneis SSH para encaminhar a porta 22 para o VPS, para que, por exemplo, um roteador do apartamento 10022 esteja disponível na porta 2 do VPS e um roteador do apartamento 11122 estará disponível na porta 3 do VPS roteador do apartamento XNUMX. É melhor configurar o encaminhamento com o mesmo sshtunnel, pois ele restaurará o túnel caso ele caia.

O túnel está configurado, você pode se conectar ao SSH através da porta encaminhada:

ssh root@МОЙ_VPS -p 10022

Em seguida, desative o OpenVPN:

/etc/init.d/openvpn stop

Agora vamos configurar um túnel GRE no roteador do apartamento 2:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set grelan0 up

E adicione a interface criada à ponte:

brctl addif br-lan grelan0

Vamos realizar um procedimento semelhante no roteador do servidor:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set grelan0 up

E, também, adicione a interface criada à ponte:

brctl addif br-lan grelan0

a partir deste momento, os pings começam a ir com sucesso para a nova rede e eu, com satisfação, vou tomar café. Então, para ver como funciona a rede do outro lado da linha, tento fazer o SSH em um dos computadores do apartamento 2, mas o cliente ssh congela sem solicitar uma senha. Tento me conectar a este computador via telnet na porta 22 e vejo uma linha da qual dá para entender que a conexão está sendo estabelecida, o servidor SSH está respondendo, mas por algum motivo não me oferece para entrar.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Estou tentando conectar via VNC e vejo uma tela preta. Eu me convenço de que o problema está no computador remoto, pois posso me conectar facilmente ao roteador deste apartamento usando o endereço interno. No entanto, decido fazer SSH neste computador por meio do roteador e fico surpreso ao descobrir que a conexão é bem-sucedida e o computador remoto funciona bem, mas também não consegue se conectar ao meu computador.

Tiro o dispositivo grelan0 da ponte e inicio o OpenVPN no roteador do apartamento 2 e certifico-me de que a rede está funcionando corretamente novamente e que as conexões não estão caindo. Pesquisando me deparo com fóruns onde as pessoas reclamam dos mesmos problemas, onde são aconselhadas a aumentar o MTU. Dito e feito. No entanto, até que o MTU fosse definido para um valor grande o suficiente de 7000 para dispositivos gretap, foram observadas conexões TCP perdidas ou transmissões lentas. Devido ao alto MTU para gretap, os MTUs para conexões WireGuard do primeiro e segundo níveis foram definidos para 8000 e 7500, respectivamente.

Fiz uma configuração semelhante no roteador do apartamento 3, com a única diferença de que uma segunda interface gretap chamada grelan1 foi adicionada ao roteador do servidor, que também foi adicionado à ponte br-lan.

Tudo está funcionando. Agora você pode colocar o conjunto gretap no carregamento automático. Por esta:

Coloquei essas linhas em /etc/rc.local no roteador do apartamento 2:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Adicionado a /etc/rc.local no roteador no apartamento 3:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

E no roteador do servidor:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

ip link add grelan1 type gretap remote 192.168.31.3 local 192.168.31.1
ip link set dev grelan1 mtu 7000
ip link set grelan1 up
brctl addif br-lan grelan1

Depois de reiniciar os roteadores clientes, descobri que, por algum motivo, eles não se conectavam ao servidor. Conectando-se ao SSH deles (felizmente, eu já havia configurado o sshtunnel para isso), foi descoberto que o WireGuard, por algum motivo, cria uma rota para o endpoint, embora esteja incorreta. Assim, para 192.168.30.2, a tabela de rotas foi especificada na tabela de rotas pela interface pppoe-wan, ou seja, pela Internet, embora a rota para ela devesse ter sido direcionada pela interface wg0. Depois de excluir esta rota, a conexão foi restaurada. Não consegui encontrar instruções em nenhum lugar sobre como forçar o WireGuard a não criar essas rotas. Além disso, nem entendi se isso é um recurso do OpenWRT ou do próprio WireGuard. Sem ter que lidar com esse problema por muito tempo, simplesmente adicionei aos dois roteadores em um script loopado por um timer, uma linha que apagou essa rota:

route del 192.168.30.2

Resumindo

Ainda não consegui uma rejeição completa do OpenVPN, pois às vezes preciso me conectar a uma nova rede de um laptop ou telefone, e configurar um dispositivo Gretap neles geralmente é impossível, mas, apesar disso, obtive uma vantagem na transferência de dados velocidade entre apartamentos e, por exemplo, usar VNC não é mais inconveniente. O ping diminuiu ligeiramente, mas ficou mais estável:

Ao usar o OpenVPN:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=133 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=125 ms

--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19006ms
rtt min/avg/max/mdev = 124.722/126.152/136.907/3.065 ms

Ao usar o WireGuard:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=124 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=124 ms
--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19003ms
rtt min/avg/max/mdev = 123.954/124.423/126.708/0.675 ms

É afetado principalmente por ping alto para VPS, que é de aproximadamente 61.5ms

No entanto, a velocidade aumentou significativamente. Assim, em um apartamento com roteador-servidor, tenho uma velocidade de conexão à Internet de 30 Mbps e, em outros apartamentos, de 5 Mbps. Ao mesmo tempo, ao usar o OpenVPN, não consegui uma taxa de transferência de dados entre redes de mais de 3,8 Mbps de acordo com o iperf, enquanto o WireGuard "bombeou" até os mesmos 5 Mbps.

Configuração do WireGuard no VPS[Interface] Address = 192.168.30.1/24
ListenPort = 51820
PrivateKey = <ЗАКРЫТЫЙ_КЛЮЧ_ДЛЯ_VPS>

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_1_МС>
AllowedIPs = 192.168.30.2/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2>
AllowedIPs = 192.168.30.3/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3>
AllowedIPs = 192.168.30.4/32

Configuração do WireGuard no MS (adicionado a /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.2/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МС'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option route_allowed_ips '1'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - сервер
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option listen_port '51821'
        list addresses '192.168.31.1/24'
        option auto '1'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list allowed_ips '192.168.31.2'

config wireguard_wg1ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3

        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list allowed_ips '192.168.31.3'

Configuração do WireGuard no MK2 (adicionado a /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.3/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК2'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list addresses '192.168.31.2/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

Configuração do WireGuard no MK3 (adicionado a /etc/config/network)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.4/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК3'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list addresses '192.168.31.3/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

Nas configurações descritas para a VPN de segundo nível, especifico a porta 51821 para clientes WireGuard. Em teoria, isso não é necessário, pois o cliente estabelecerá uma conexão de qualquer porta livre não privilegiada, mas fiz para que todas as conexões de entrada pode ser negado nas interfaces wg0 de todos os roteadores, exceto conexões UDP de entrada na porta 51821.

Espero que o artigo seja útil para alguém.

PS Além disso, quero compartilhar meu script que me envia uma notificação PUSH para meu telefone no aplicativo WirePusher quando um novo dispositivo aparece em minha rede. Aqui está um link para o script: github.com/r0ck3r/device_discover.

ATUALIZAR: Servidor OpenVPN e configuração de clientes

Servidor OpenVPN

client-to-client

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/vpn-server.crt
dh /etc/openvpn/server/dh.pem
key /etc/openvpn/server/vpn-server.key

dev tap
ifconfig-pool-persist /etc/openvpn/ipp.txt 0
keepalive 10 60
proto tcp4
server-bridge 192.168.10.1 255.255.255.0 192.168.10.80 192.168.10.254
status /var/log/openvpn-status.log
verb 3
comp-lzo

Cliente OpenVPN

client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Change to your router's External IP
resolv-retry infinite
nobind

ca client/ca.crt
cert client/client.crt
key client/client.key
dh client/dh.pem

comp-lzo
persist-tun
persist-key
verb 3

Usei o easy-rsa para gerar certificados.

Fonte: habr.com

Adicionar um comentário