
Vorrei condividere la mia esperienza di unione di reti in tre appartamenti geograficamente distanti, ciascuno dei quali utilizza router con OpenWRT come gateway, in un'unica rete comune. Nella scelta del metodo di unione delle reti tra L3 con routing delle sottoreti e L2 con bridging, in cui tutti i nodi della rete si trovano nella stessa sottorete, è stata preferita la seconda opzione, più complessa da configurare, ma che offre maggiore possibilità, in quanto nella rete creata era previsto l'uso trasparente delle tecnologie Wake-on-Lan e DLNA.
Parte 1: Storia
Come protocollo per implementare questa soluzione è stato scelto inizialmente OpenVPN, poiché, in primo luogo, può creare un dispositivo tap che si integra facilmente in un bridge, e in secondo luogo, OpenVPN supporta il funzionamento tramite protocollo TCP, il che era molto importante, visto che in nessuno degli appartamenti era presente un indirizzo IP dedicato. Non sono riuscito a utilizzare STUN perché il mio provider blocca misteriosamente le connessioni in entrata tramite il protocollo UDP dalle proprie reti, mentre il protocollo TCP mi permetteva di inoltrare la porta del server VPN su un VPS noleggiato tramite SSH. Sì, questo approccio genera un carico maggiore, poiché i dati vengono criptati due volte, ma non volevo inserire il VPS nella mia rete privata, poiché rimaneva il rischio che terze parti potessero avere accesso a esso; quindi avere un dispositivo di questo tipo nella rete domestica era estremamente indesiderabile e ho deciso di pagare per la sicurezza con un sovraccarico maggiore.
Per il port forwarding sul router, sul quale era prevista la creazione del server, è stato utilizzato il programma sshtunnel. Non mi soffermerò sui dettagli della sua configurazione — è abbastanza semplice. Voglio solo notare che il suo compito era quello di eseguire il port forwarding della porta TCP 1194 dal router al VPS. Successivamente, è stato configurato un server OpenVPN sull'interfaccia tap0, che è stata inserita nel bridge br-lan. Verificando la connessione al server appena creato dal laptop, è diventato chiaro che l'idea del port forwarding si è dimostrata valida e il mio laptop è diventato un membro della rete del router, anche se fisicamente non si trovava al suo interno.
Rimaneva solo un piccolo passo: era necessario distribuire gli indirizzi IP in diversi appartamenti in modo che non ci fossero conflitti e configurare i router come client OpenVPN.
Sono stati scelti i seguenti indirizzi IP per i router e i range dei server DHCP:
- 192.168.10.1 con il range 192.168.10.2 — 192.168.10.80 per il server
- 192.168.10.100 con il range 192.168.10.101 — 192.168.10.149 per il router nell'appartamento n. 2
- 192.168.10.150 con il range 192.168.10.151 — 192.168.10.199 per il router nell'appartamento n. 3
Era anche necessario assegnare esattamente questi indirizzi ai router client del server OpenVPN, aggiungendo la seguente riga alla sua configurazione:
ifconfig-pool-persist /etc/openvpn/ipp.txt 0e aggiungendo le seguenti righe nel 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 creazione dei certificati per la connessione a OpenVPN
Successivamente, sono stati configurati i client OpenVPN sui router, e i dispositivi tap0 su entrambi sono stati aggiunti al bridge br-lan. A questo punto sembrava che tutto funzionasse correttamente, poiché tutte e tre le reti si vedevano a vicenda e operavano come un'unica entità. Tuttavia, emerse un dettaglio poco piacevole: a volte i dispositivi ricevevano un indirizzo IP non dal proprio router, con tutte le conseguenze del caso. Per qualche motivo, il router in uno degli appartamenti non riusciva a rispondere in tempo ai DHCPDISCOVER e il dispositivo riceveva un indirizzo non corretto. Ho capito che era necessario filtrare tali richieste in tap0 su ciascuno dei router, ma, come si è scoperto, iptables non può lavorare con un dispositivo che è parte di un bridge e ho dovuto allenare ebtables per aiutarmi. Purtroppo, nelle mie versioni firmware non era presente, quindi ho dovuto ricompilare le immagini per ogni dispositivo. Fatto ciò e aggiunte quelle 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: Introduzione a WireGuard
Negli ultimi tempi si è parlato sempre più frequentemente di WireGuard, elogiandone la facilità di configurazione, l'alta velocità di trasmissione e il ping ridotto a fronte di una sicurezza comparabile. Cercare ulteriori informazioni mi ha fatto capire che né l'operatività come membro di un ponte né l'uso del protocollo TCP sono supportati, il che mi faceva pensare che alternative a OpenVPN per me non fossero ancora disponibili. Così ho rimandato l'incontro con WireGuard.
Qualche giorno fa, nelle risorse legate all'IT, è circolata la notizia che WireGuard sarebbe finalmente stato incluso nel kernel di Linux, a partire dalla versione 5.6. Gli articoli di notizie, come sempre, lodavano WireGuard. Sono tornato a cercare modi per sostituire il vecchio affezionato OpenVPN. Questa volta mi sono imbattuto in . Si parlava della creazione di un tunnel Ethernet sopra L3 tramite GRE. Questo articolo mi ha dato speranza. Rimaneva poco chiaro come gestire il protocollo UDP. La ricerca mi ha portato ad articoli sull'uso di socat in combinazione con un tunnel SSH per il forwarding della porta UDP, ma in essi si sottolineava che tale approccio funziona solo in modalità di una connessione, il che rende impossibile il funzionamento di più client VPN. Mi è venuta l'idea di avviare un server VPN su un VPS e configurare GRE per i clienti, ma, come si è rivelato, GRE non supporta la crittografia, il che porterebbe al fatto che nel caso di accesso al server da terze parti, tutto il traffico tra le mie reti sarebbe nelle loro mani, cosa che non mi andava bene in linea di principio.
È stata nuovamente presa la decisione a favore di una crittografia ridondante, utilizzando VPN sopra VPN secondo il seguente schema:
VPN di primo livello:
VPS è server con indirizzo interno 192.168.30.1
MC è client VPS con indirizzo interno 192.168.30.2
MC2 è client VPS con indirizzo interno 192.168.30.3
MC3 è client VPS con indirizzo interno 192.168.30.4
VPN di secondo livello:
MC è server con indirizzo esterno 192.168.30.2 e interno 192.168.31.1
MC2 è client MC con indirizzo 192.168.30.2 e ha IP interno 192.168.31.2
MC3 è client MC con l'indirizzo 192.168.30.2 e con un IP interno 192.168.31.3
* MC — router-server nell'appartamento 1, MC2 — router nell'appartamento 2, MC3 — router nell'appartamento 3
* Le configurazioni dei dispositivi sono pubblicate nel spoiler alla fine dell'articolo.
Quindi, i ping tra i nodi della rete 192.168.31.0/24 funzionano, è ora di configurare il tunnel GRE. Prima di ciò, per non perdere l'accesso ai router, è opportuno configurare tunnel SSH per il forwarding della porta 22 su VPS, in modo tale che, ad esempio, sulla porta 10022 il VPS sarà accessibile dal router dell'appartamento 2, e sulla porta 11122 il VPS sarà accessibile dal router dell'appartamento 3. È meglio eseguire la configurazione del forwarding con sshtunnel, poiché questo ripristinerà il tunnel in caso di caduta.
Tunnel configurato, puoi connetterti a SSH attraverso la porta forwarding:
ssh root@IL_MIO_VPS -p 10022Ora bisogna disattivare OpenVPN:
/etc/init.d/openvpn stopAdesso configuriamo il tunnel GRE sul router dell'appartamento 2:
ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set grelan0 up
E aggiungiamo l'interfaccia creata al bridge:
brctl addif br-lan grelan0
Effettueremo la stessa procedura sul router-server:
ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set grelan0 up
E, inoltre, aggiungiamo l'interfaccia creata al bridge:
brctl addif br-lan grelan0
Da questo momento in poi, i ping iniziano a transitare con successo nella nuova rete e io, con soddisfazione, mi avvio a prendere un caffè. Poi, per valutare come funziona la rete dall'altra parte del cavo, cerco di connettermi via SSH a uno dei computer nell'appartamento 2, ma il client SSH ‘si blocca’, senza offrirmi di inserire la password. Provo a collegarmi a quel computer tramite telnet sulla porta 22 e vedo una riga che indica che la connessione si sta stabilendo, il server SSH risponde, solo per qualche motivo non mi offre di entrare.
$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1
Cerco di connettermi a lui anche tramite VNC e vedo uno schermo nero. Mi convinco che il problema sia nel computer remoto, poiché posso connettermi al router di quell'appartamento usando l'indirizzo interno. Tuttavia, decido di connettermi tramite SSH a quel computer attraverso il router e con sorpresa scopro che la connessione riesce e il computer remoto funziona perfettamente, ma non riesce nemmeno a connettersi al mio computer.
Ho disconnesso il dispositivo grelan0 dal ponte e avviato OpenVPN sul router dell'appartamento 2, assicurandomi che la rete funzionasse di nuovo correttamente e che le connessioni non venissero interrotte. Navigando in rete, sono incappato in forum in cui le persone lamentavano problemi simili, e consigliavano di aumentare l'MTU. Detto fatto. Tuttavia, mentre l'MTU non era stato impostato sufficientemente alto — 7000 per i dispositivi gretap — si osservavano interruzioni delle connessioni TCP o basse velocità di trasferimento. A causa dell'elevato MTU per gretap, l'MTU per le connessioni WireGuard di primo e secondo livello è stato impostato rispettivamente a 8000 e 7500.
Ho effettuato un'impostazione simile anche sul router dell'appartamento 3, con l'unica differenza che sul router server è stato aggiunto un secondo'interfaccia gretap chiamata grelan1, anch'essa integrata nel ponte br-lan.
Tutto funziona. Ora posso inserire il setup gretap nell'avvio automatico. Per fare ciò:
Ho inserito queste righe in /etc/rc.local sul router dell'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
Ho aggiunto questo a /etc/rc.local sul router dell'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-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 il riavvio dei router client ho scoperto che per qualche motivo non si collegano al server. Collegandomi al loro SSH (fortunatamente, avevo configurato in precedenza sshtunnel per questo) ho scoperto che WireGuard per qualche motivo crea una rotta per l'endpoint, ma in modo errato. Per esempio, per 192.168.30.2 nella tabella delle rotte era indicata una rotta tramite l'interfaccia pppoe-wan, cioè tramite internet, mentre la rotta verso di essa doveva essere diretta tramite l'interfaccia wg0. Dopo aver rimosso questa rotta, la connessione è stata ripristinata. Non sono riuscito a trovare istruzioni su come far sì che WireGuard non crei queste rotte. Inoltre, non ho capito se sia una caratteristica di OpenWRT o di WireGuard stesso. Senza voler perdere tempo a risolvere questo problema, ho semplicemente aggiunto su entrambi i router in uno script, ciclicamente, la riga che eliminava questa rotta:
route del 192.168.30.2
In conclusione
Non sono ancora riuscito a dismettere completamente OpenVPN, poiché a volte ho bisogno di connettermi a una nuova rete dal laptop o dal telefono, e la configurazione del dispositivo gretap su di essi è generalmente impossibile. Tuttavia, nonostante ciò, ho ottenuto un vantaggio nella velocità di trasferimento dei dati tra gli appartamenti e, ad esempio, l'uso di VNC ora non causa fastidi. Il ping è diminuito leggermente, ma è diventato più stabile:
Utilizzando 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
--- Statistiche ping di 192.168.10.110 ---
20 pacchetti trasmessi, 20 ricevuti, 0% di perdita di pacchetti, tempo 19006ms
rtt min/avg/max/mdev = 124.722/126.152/136.907/3.065 ms
Utilizzando 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
--- Statistiche ping di 192.168.10.110 ---
20 pacchetti trasmessi, 20 ricevuti, 0% di perdita di pacchetti, tempo 19003ms
rtt min/avg/max/mdev = 123.954/124.423/126.708/0.675 ms
Ad influenzarlo maggiormente è un ping elevato verso il VPS, che è di circa 61,5 ms
Tuttavia, la velocità è aumentata significativamente. Così, nell'appartamento con il router-server ho una velocità di connessione a Internet di 30 Mbit/s, mentre negli altri appartamenti di 5 Mbit/s. Durante l'utilizzo di OpenVPN, non sono riuscito a raggiungere una velocità di trasferimento dati tra le reti superiore a 3,8 Mbit/s secondo le misurazioni di iperf, mentre WireGuard "ha portato" la velocità a 5 Mbit/s.
Configurazione di WireGuard su VPS[Interface]
Indirizzo = 192.168.30.1/24
PortaDiAscolto = 51820
ChiavePrivata =
[Peer]
PublicKey =
AllowedIPs = 192.168.30.2/32
[Peer]
PublicKey =
AllowedIPs = 192.168.30.3/32
[Peer]
PublicKey =
AllowedIPs = 192.168.30.4/32
Configurazione di WireGuard su MS (da aggiungere in /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 di WireGuard su MK2 (da aggiungere in /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 di WireGuard su MK3 (da aggiungere in /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 il VPN di secondo livello, indico ai clienti di utilizzare WireGuard sulla porta 51821. In teoria non è necessario, poiché il client stabilirà la connessione su qualsiasi porta non privilegiata libera, ma ho fatto in questo modo per poter vietare tutte le connessioni in entrata sulle interfacce wg0 di tutti i router, tranne le connessioni UDP in entrata sulla porta 51821.
Spero che l'articolo possa essere utile a qualcuno.
P.S. Inoltre, voglio condividere il mio script che mi invia una notifica PUSH sul telefono nell'app WirePusher quando un nuovo dispositivo appare nella mia rete. Ecco il link allo script: .
AGGIORNAMENTO: Configurazione del server e dei 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-lzoClient OpenVPN
client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Cambia con l'IP Esterno del tuo router
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 Per generare i certificati ho utilizzato easy-rsa
Fonte: habr.com
