Migrazione da OpenVPN a WireGuard per consolidare le reti in un'unica rete L2

Migrazione da OpenVPN a WireGuard per consolidare le reti in un'unica rete L2

Vorrei condividere la mia esperienza di combinazione di reti in tre appartamenti geograficamente distanti, ognuno dei quali utilizza router con OpenWRT come gateway, in una rete comune. Quando si sceglie un metodo per combinare le reti tra L3 con instradamento sottorete e L2 con bridging, quando tutti i nodi di rete saranno nella stessa sottorete, è stata data preferenza al secondo metodo, che è più difficile da configurare, ma offre maggiori opportunità, poiché trasparente è stato pianificato l'utilizzo delle tecnologie nella rete creata Wake-on-Lan e DLNA.

Parte 1: Contesto

OpenVPN è stato inizialmente scelto come protocollo per l'implementazione di questa attività, poiché, in primo luogo, può creare un dispositivo di tocco che può essere aggiunto al bridge senza problemi e, in secondo luogo, OpenVPN supporta il funzionamento tramite il protocollo TCP, anch'esso importante, perché nessuno degli appartamenti aveva un indirizzo IP dedicato e non ero in grado di utilizzare STUN, perché per qualche motivo il mio ISP bloccava le connessioni UDP in entrata dalle loro reti, mentre il protocollo TCP mi permetteva di inoltrare la porta del server VPN sul VPS noleggiato tramite SSH. Sì, questo approccio dà un grosso carico, poiché i dati vengono crittografati due volte, ma non volevo introdurre il VPS nella mia rete privata, poiché c'era ancora il rischio che terze parti ne prendessero il controllo, quindi, avendo un tale dispositivo sulla rete domestica era estremamente indesiderabile e si è deciso di pagare per la sicurezza con un grande sovraccarico.

Per inoltrare la porta sul router su cui era previsto il deployment del server, è stato utilizzato il programma sshtunnel. Non descriverò le complessità della sua configurazione: questo viene fatto abbastanza facilmente, noto solo che il suo compito era inoltrare la porta TCP 1194 dal router al VPS. Successivamente, il server OpenVPN è stato configurato sul dispositivo tap0, che era connesso al bridge br-lan. Dopo aver verificato la connessione al server appena creato dal laptop, è diventato chiaro che l'idea del port forwarding si giustificava da sola e il mio laptop è diventato un membro della rete del router, sebbene non fosse fisicamente presente.

La questione è rimasta piccola: era necessario distribuire gli indirizzi IP in diversi appartamenti in modo che non entrassero in conflitto e configurare i router come client OpenVPN.
Sono stati selezionati i seguenti indirizzi IP del router e intervalli di server DHCP:

  • 192.168.10.1 con gamma 192.168.10.2 - 192.168.10.80 per il servitore
  • 192.168.10.100 con gamma 192.168.10.101 - 192.168.10.149 per un router nell'appartamento n. 2
  • 192.168.10.150 con gamma 192.168.10.151 - 192.168.10.199 per un router nell'appartamento n. 3

Era inoltre necessario assegnare esattamente questi indirizzi ai router client del server OpenVPN aggiungendo la riga alla sua configurazione:

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

e aggiungendo le seguenti righe al file /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

dove flat1_id e flat2_id sono i nomi dei dispositivi specificati durante la generazione dei certificati per la connessione a OpenVPN

Successivamente, i client OpenVPN sono stati configurati sui router, i dispositivi tap0 su entrambi sono stati aggiunti al bridge br-lan. In questa fase, tutto sembrava essere in ordine, poiché tutte e tre le reti si vedono e funzionano nel loro insieme. Tuttavia, è emerso un dettaglio non molto piacevole: a volte i dispositivi potrebbero ottenere un indirizzo IP non dal proprio router, con tutte le conseguenze che ne derivano. Per qualche motivo, il router in uno degli appartamenti non ha avuto il tempo di rispondere in tempo a DHCPDISCOVER e il dispositivo ha ricevuto l'indirizzo sbagliato. Mi sono reso conto che devo filtrare tali richieste in tap0 su ciascuno dei router, ma come si è scoperto, iptables non può funzionare con un dispositivo se fa parte di un bridge e ebtables dovrebbe venire in mio soccorso. Con mio rammarico, non era nel mio firmware e ho dovuto ricostruire le immagini per ogni dispositivo. In questo modo e aggiungendo queste righe a /etc/rc.local di ciascun router, il problema è stato risolto:

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

Questa configurazione è durata tre anni.

Parte 2: Presentazione di WireGuard

Di recente, Internet ha parlato sempre più di WireGuard, ammirando la semplicità della sua configurazione, l'elevata velocità di trasferimento, il basso ping con una sicurezza comparabile. La ricerca di ulteriori informazioni al riguardo ha chiarito che né il lavoro come membro bridge né il lavoro tramite il protocollo TCP sono supportati da esso, il che mi ha fatto pensare che non ci siano ancora alternative a OpenVPN per me. Quindi ho rimandato la conoscenza di WireGuard.

Qualche giorno fa, attraverso le risorse in un modo o nell'altro legate all'IT, si è diffusa la notizia che WireGuard sarà finalmente incluso nel kernel Linux, a partire dalla versione 5.6. Gli articoli di notizie, come sempre, hanno elogiato WireGuard. Mi sono immerso di nuovo nella ricerca di modi per sostituire il buon vecchio OpenVPN. Questa volta mi sono imbattuto questo articolo. Ha parlato della creazione di un tunnel Ethernet su L3 utilizzando GRE. Questo articolo mi ha dato speranza. Non è chiaro cosa fare con il protocollo UDP. La ricerca mi ha portato ad articoli sull'utilizzo di socat in combinazione con un tunnel SSH per inoltrare una porta UDP, tuttavia, hanno notato che questo approccio funziona solo in modalità di connessione singola, il che significa che più client VPN sarebbero impossibili. Mi è venuta l'idea di configurare un server VPN su un VPS e configurare GRE per i client, ma come si è scoperto, GRE non supporta la crittografia, il che porterà al fatto che se terze parti ottengono l'accesso al server , tutto il traffico tra le mie reti è nelle loro mani, il che non mi andava affatto bene.

Anche in questo caso, la decisione è stata presa a favore della crittografia ridondante, utilizzando VPN su VPN secondo il seguente schema:

VPN di livello XNUMX:
VPS è server con indirizzo interno 192.168.30.1
MS è cliente VPS con indirizzo interno 192.168.30.2
МК2 è cliente VPS con indirizzo interno 192.168.30.3
МК3 è cliente VPS con indirizzo interno 192.168.30.4

VPN di livello XNUMX:
MS è server con indirizzo esterno 192.168.30.2 e interno 192.168.31.1
МК2 è cliente MS con l'indirizzo 192.168.30.2 e ha un IP interno di 192.168.31.2
МК3 è cliente MS con l'indirizzo 192.168.30.2 e ha un IP interno di 192.168.31.3

* MS - router-server nell'appartamento 1, МК2 - router nell'appartamento 2, МК3 - router nell'appartamento 3
*Le configurazioni del dispositivo sono pubblicate nello spoiler a fine articolo.

E così, i ping tra i nodi della rete 192.168.31.0/24 vanno, è ora di passare alla configurazione del tunnel GRE. Prima di ciò, per non perdere l'accesso ai router, vale la pena impostare tunnel SSH per inoltrare la porta 22 al VPS, in modo che, ad esempio, sulla porta 10022 del VPS sia disponibile un router dell'appartamento 2 e un il router dell'appartamento 11122 sarà disponibile sulla porta 3 del VPS router dell'appartamento XNUMX. È meglio configurare l'inoltro con lo stesso sshtunnel, poiché ripristinerà il tunnel in caso di caduta.

Il tunnel è configurato, puoi connetterti a SSH tramite la porta inoltrata:

ssh root@МОЙ_VPS -p 10022

Successivamente, disabilita OpenVPN:

/etc/init.d/openvpn stop

Ora impostiamo un tunnel GRE sul router dall'appartamento 2:

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

E aggiungi l'interfaccia creata al bridge:

brctl addif br-lan grelan0

Eseguiamo una procedura simile sul router del server:

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

E, inoltre, aggiungi l'interfaccia creata al bridge:

brctl addif br-lan grelan0

a partire da questo momento i ping iniziano ad andare con successo alla nuova rete ed io, con soddisfazione, vado a bere il caffè. Quindi, per vedere come funziona la rete dall'altra parte del cavo, provo a entrare in SSH in uno dei computer nell'appartamento 2, ma il client ssh si blocca senza chiedermi una password. Provo a connettermi a questo computer tramite telnet sulla porta 22 e vedo una linea da cui si capisce che si sta stabilendo la connessione, il server SSH risponde, ma per qualche motivo non mi offre di entrare.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Sto provando a connettermi tramite VNC e vedo uno schermo nero. Mi convinco che la questione sia nel computer remoto, perché posso facilmente connettermi al router da questo appartamento utilizzando l'indirizzo interno. Tuttavia, decido di accedere a questo computer tramite SSH tramite il router e sono sorpreso di scoprire che la connessione ha esito positivo e che il computer remoto funziona correttamente, ma non riesce nemmeno a connettersi al mio computer.

Prendo il dispositivo grelan0 dal bridge e avvio OpenVPN sul router nell'appartamento 2 e mi assicuro che la rete funzioni di nuovo correttamente e che le connessioni non si interrompano. Cercando mi imbatto in forum in cui le persone si lamentano degli stessi problemi, dove viene consigliato di aumentare l'MTU. Detto fatto. Tuttavia, fino a quando l'MTU non è stato impostato su un valore sufficientemente elevato di 7000 per i dispositivi gretap, sono state osservate connessioni TCP interrotte o trasmissioni lente. A causa dell'elevato MTU per gretap, gli MTU per le connessioni WireGuard di primo e secondo livello sono stati impostati rispettivamente a 8000 e 7500.

Ho eseguito una configurazione simile sul router dell'appartamento 3, con l'unica differenza che una seconda interfaccia gretap denominata grelan1 è stata aggiunta al router del server, che è stata aggiunta anche al bridge br-lan.

Funziona tutto. Ora puoi mettere l'assieme gretap in caricamento automatico. Per questo:

Ho inserito queste righe in /etc/rc.local sul router nell'appartamento 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

Aggiunto questo a /etc/rc.local sul router nell'appartamento 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 sul router del server:

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

Dopo aver riavviato i router client, ho scoperto che per qualche motivo non si connettevano al server. Collegandosi al loro SSH (fortunatamente, avevo precedentemente configurato sshtunnel per questo), è stato scoperto che WireGuard per qualche motivo crea un percorso per l'endpoint, pur essendo errato. Quindi, per 192.168.30.2, la tabella di instradamento è stata specificata nella tabella di instradamento tramite l'interfaccia pppoe-wan, ovvero tramite Internet, sebbene il percorso verso di esso avrebbe dovuto essere diretto tramite l'interfaccia wg0. Dopo aver eliminato questo percorso, la connessione è stata ripristinata. Non sono riuscito a trovare istruzioni da nessuna parte su come forzare WireGuard a non creare questi percorsi. Inoltre, non ho nemmeno capito se questa è una funzionalità di OpenWRT o di WireGuard stesso. Senza dover affrontare questo problema per molto tempo, ho semplicemente aggiunto a entrambi i router in uno script ripetuto da un timer, una riga che cancellava questo percorso:

route del 192.168.30.2

Riassumendo

Non ho ancora ottenuto un completo rifiuto di OpenVPN, poiché a volte ho bisogno di connettermi a una nuova rete da un laptop o telefono e la configurazione di un dispositivo gretap su di essi è generalmente impossibile, ma nonostante ciò, ho ottenuto un vantaggio nel trasferimento dei dati la velocità tra gli appartamenti e, ad esempio, l'utilizzo di VNC non è più scomodo. Il ping è leggermente diminuito, ma è diventato più stabile:

Quando si utilizza 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

Quando si utilizza 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

È principalmente influenzato da un ping elevato verso VPS che è di circa 61.5 ms

Tuttavia, la velocità è aumentata in modo significativo. Quindi, in un appartamento con router-server, ho una velocità di connessione a Internet di 30 Mbps e in altri appartamenti di 5 Mbps. Allo stesso tempo, durante l'utilizzo di OpenVPN, non sono riuscito a raggiungere una velocità di trasferimento dati tra reti superiore a 3,8 Mbps secondo iperf, mentre WireGuard l'ha "pompata" fino agli stessi 5 Mbps.

Configurazione WireGuard su 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

Configurazione WireGuard su MS (aggiunto 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'

Configurazione WireGuard su MK2 (aggiunto 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'

Configurazione WireGuard su MK3 (aggiunto 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'

Nelle configurazioni descritte per la VPN di secondo livello, ai client WireGuard specifico la porta 51821. In teoria, questo non è necessario, poiché il client stabilirà una connessione da qualsiasi porta libera non privilegiata, ma ho fatto in modo che tutte le connessioni in entrata può essere negato sulle interfacce wg0 di tutti i router, ad eccezione delle connessioni UDP in entrata sulla porta 51821.

Spero che l'articolo sia utile a qualcuno.

PS Inoltre, voglio condividere il mio script che mi invia una notifica PUSH al mio telefono nell'applicazione WirePusher quando un nuovo dispositivo appare sulla mia rete. Ecco un link allo script: github.com/r0ck3r/device_discover.

AGGIORNARE: Configurazione server e client OpenVPN

Server 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

Ho usato easy-rsa per generare certificati.

Fonte: habr.com

Aggiungi un commento