
Vorrei condividere la mia esperienza di unione di reti in tre appartamenti geograficamente distanti, in ciascuno dei quali i router con OpenWRT vengono utilizzati come gateway, in una rete comune. Nella scelta del modo di unire le reti tra L3 con routing delle sottoreti e L2 con bridging, dove tutti i nodi della rete si trovano nella stessa sottorete, è stata preferita quest'ultima approccio, più complesso da configurare, ma con maggiori possibilità, poiché nella rete che si stava creando si intendeva utilizzare in modo trasparente le tecnologie Wake-on-Lan e DLNA.
Parte 1: Antefatto
Inizialmente, per realizzare questo compito, è stato scelto il protocollo OpenVPN, poiché, in primo luogo, può creare un dispositivo tap che si aggiunge senza problemi al bridge, e in secondo luogo, OpenVPN supporta il funzionamento tramite protocollo TCP, il che era anche molto importante, dato che nessuno degli appartamenti aveva un indirizzo IP statico, e non sono riuscito a utilizzare STUN, poiché il mio provider blocca misteriosamente le connessioni in entrata tramite protocollo UDP dalle proprie reti, mentre il protocollo TCP mi ha permesso di inoltrare la porta del server VPN su un VPS affittato tramite SSH. Sì, questo approccio comporta un grande carico, poiché i dati vengono crittografati due volte, ma non ho voluto integrare il VPS nella mia rete privata, poiché rimaneva il rischio di terze parti che ottenessero il controllo su di esso, quindi avere un dispositivo del genere nella rete domestica era estremamente indesiderabile e si è deciso di pagare per la sicurezza con un maggiore overhead.
Per l'inoltro della porta sul router, su cui si intendeva distribuire il server, è stato utilizzato il programma sshtunnel. Non entrerò nei dettagli della sua configurazione — è un'operazione piuttosto semplice, ma sottolineerò che il suo obiettivo era l'inoltro della porta TCP 1194 dal router al VPS. Successivamente, è stato configurato un server OpenVPN sul dispositivo tap0, che è stato collegato al bridge br-lan. Controllando la connessione al server appena creato con il mio laptop — è diventato chiaro che l'idea di inoltrare la porta si era rivelata efficace e il mio laptop era diventato membro della rete del router, anche se fisicamente non vi si trovava.
Restava solo un ultimo passo: era necessario assegnare gli indirizzi IP negli appartamenti diversi in modo che non ci fossero conflitti e configurare i router come client OpenVPN.
Sono stati scelti i seguenti indirizzi IP dei router e intervalli dei server DHCP:
- 192.168.10.1 con intervallo 192.168.10.2 — 192.168.10.80 per il server
- 192.168.10.100 con intervallo 192.168.10.101 — 192.168.10.149 per il router nell'appartamento n. 2
- 192.168.10.150 con intervallo 192.168.10.151 — 192.168.10.199 per il router nell'appartamento n. 3
È stato anche necessario assegnare questi indirizzi ai router client del server OpenVPN, aggiungendo nella sua configurazione la seguente riga:
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
In seguito, i client OpenVPN sono stati configurati sui router, i dispositivi tap0 su entrambi sono stati aggiunti al ponte br-lan. A questo punto sembrava che tutto funzionasse correttamente, poiché tutte e tre le reti si vedevano e lavoravano come un'unica entità. Tuttavia, è emerso un dettaglio sgradevole: a volte i dispositivi potevano ricevere 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 a DHCPDISCOVER e il dispositivo riceveva un indirizzo non suo. Ho capito che dovevo filtrare tali richieste in tap0 su ciascuno dei router, ma, come si è rivelato, iptables non può funzionare con un dispositivo se fa parte di un ponte e ho dovuto fare affidamento su ebtables. Sfortunatamente, nelle mie versioni del firmware non era presente e ho dovuto ricompilare le immagini per ciascun dispositivo. Dopo aver fatto ciò e aggiungendo queste righe in /etc/rc.local di ogni 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 per tre anni.
Parte 2: Introduzione a WireGuard
Negli ultimi tempi si è parlato sempre più di WireGuard, lodandone la semplicità di configurazione, l'alta velocità di trasferimento e il ping basso a fronte di una sicurezza comparabile. La ricerca di ulteriori informazioni su di esso ha fatto capire che né il funzionamento come membro di un ponte, né il lavoro tramite il protocollo TCP sono supportati, il che mi ha fatto pensare che alternative a OpenVPN non ce ne fossero. Così ho rimandato l'incontro con WireGuard.
Qualche giorno fa, una notizia ha circolato sui portali legati all'IT, annunciando che WireGuard verrà finalmente incluso nel kernel di Linux a partire dalla versione 5.6. Gli articoli di notizie, come sempre, lodavano WireGuard. Sono tornato a cercare delle alternative al vecchio e fidato OpenVPN. Questa volta mi sono imbattuto in . Si parlava di creare un tunnel Ethernet sopra l'L3 utilizzando GRE. Questo articolo ha riacceso la mia speranza. Rimaneva però poco chiaro cosa fare con il protocollo UDP. La mia ricerca mi portava a articoli sull'uso di socat in combinazione con un tunnel SSH per il forwarding della porta UDP, tuttavia, veniva sottolineato che questo approccio funziona solo in modalità connessione singola, il che renderebbe impossibile il funzionamento di più client VPN. Mi è venuta l'idea di sollevare un server VPN su VPS e configurare GRE per i client, ma, come si è rivelato, GRE non supporta la crittografia, il che significa che nel caso di accesso al server da parte di terzi, questi avrebbero accesso all'intero traffico tra le mie reti, il che non mi soddisfaceva affatto.
Ho quindi deciso di optare per un'ulteriore crittografia, utilizzando una VPN sopra un'altra VPN secondo il seguente schema:
VPN di primo livello:
VPS è server con indirizzo interno 192.168.30.1
MS è client VPS con indirizzo interno 192.168.30.2
MK2 è client VPS con indirizzo interno 192.168.30.3
MK3 è client VPS con indirizzo interno 192.168.30.4
VPN di secondo livello:
MS è server con indirizzo esterno 192.168.30.2 e interno 192.168.31.1
MK2 è client MS con indirizzo 192.168.30.2 e un IP interno 192.168.31.2
MK3 è client MS con indirizzo 192.168.30.2 e un IP interno 192.168.31.3
* MS — router-server nell'appartamento 1, MK2 — router nell'appartamento 2, MK3 — router nell'appartamento 3
* Le configurazioni dei dispositivi sono pubblicate nel spoiler alla fine dell'articolo.
Dunque, i ping tra i nodi della rete 192.168.31.0/24 funzionano, è tempo di passare alla configurazione del tunnel GRE. Prima di questo, per non perdere l'accesso ai router, è consigliabile configurare tunnel SSH per il forwarding della porta 22 su VPS, in modo che, ad esempio, sulla porta 10022, VPS sarà accessibile il router dell'appartamento 2, e sulla porta 11122 VPS sarà accessibile il router dell'appartamento 3. È meglio eseguire la configurazione del forwarding sempre con sshtunnel, poiché esso ripristinerà il tunnel in caso di caduta.
Tunnel configurato, si può connettersi a SSH tramite la porta forwardata:
ssh root@IL_MIO_VPS -p 10022Ora è necessario 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 ponte:
brctl addif br-lan grelan0
Eseguiremo 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 ponte:
brctl addif br-lan grelan0
Da questo momento in poi i ping iniziano a passare con successo nella nuova rete e io, con soddisfazione, vado a bere caffè. Poi, per valutare come funziona la rete dall'altra parte del cavo, cerco di connettermi tramite SSH a uno dei computer nell'appartamento 2, ma il client SSH "si blocca" senza offrirmi di inserire la password. Provo a connettermi a questo computer tramite telnet sulla porta 22 e vedo una riga che fa capire che la connessione sta venendo stabilita, il server SSH risponde, ma per qualche motivo non mi invita ad entrare.
$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1
Provo a connettermi a lui tramite VNC e vedo uno schermo nero. Mi convinco che sia colpa del computer remoto, poiché posso connettermi senza problemi al router di questo appartamento tramite l'indirizzo interno. Tuttavia, decido di connettermi a SSH di questo computer tramite il router e con sorpresa scopro che la connessione riesce, e il computer remoto funziona perfettamente, ma non riesce a connettersi al mio computer.
Rimuovo il dispositivo grelan0 dal ponte e avvio OpenVPN sul router nell'appartamento 2 e mi accerto che la rete funzioni di nuovo come previsto e che le connessioni non si interrompano. Trovo sui forum persone che lamentano gli stessi problemi, a cui viene consigliato di aumentare l'MTU. Detto — fatto. Tuttavia, finché l'MTU non è stato impostato su un valore sufficientemente alto — 7000 per i dispositivi gretap, sono stati osservati interruzioni delle connessioni TCP o bassa velocità di trasferimento. A causa dell'elevato MTU per gretap, l'MTU per le connessioni WireGuard di primo e secondo livello sono stati impostati su 8000 e 7500 rispettivamente.
Ho effettuato un'impostazione simile anche sul router dell'appartamento 3, differente solo per il fatto che sul router server è stato aggiunto un secondo interfaccia gretap chiamata grelan1, che è stata anch'essa aggiunta al ponte br-lan.
Tutto funziona. Ora posso impostare la creazione di gretap per l'avvio automatico. Per fare ciò:
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
Ho aggiunto questo a /etc/rc.local sul router di casa 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 connettono al server. Collegandomi al loro SSH (per fortuna avevo configurato in anticipo sshtunnel per questo) ho scoperto che WireGuard crea inaspettatamente una route per l'endpoint, e in modo errato. Così, per 192.168.30.2 nella tabella delle route era indicata una route attraverso l'interfaccia pppoe-wan, ossia attraverso Internet, mentre la route verso di esso avrebbe dovuto essere indirizzata tramite l'interfaccia wg0. Dopo aver eliminato questa route, la connessione si è ristabilita. Non sono riuscito a trovare istruzioni su come costringere WireGuard a non creare queste route. Inoltre, non ho nemmeno capito se si tratta di una caratteristica di OpenWRT o di WireGuard stesso. Non volendo spendere troppo tempo a risolvere questo problema, ho semplicemente aggiunto a entrambi i router uno script, in ciclo temporale, con la riga che elimina questa route:
route del 192.168.30.2
In sintesi
Finora non sono riuscito a eliminare completamente OpenVPN, poiché ho bisogno di connettermi a una nuova rete con il portatile o il telefono, e la configurazione del dispositivo gretap su di essi in generale non è possibile, ma nonostante ciò, ho guadagnato in velocità di trasferimento dati tra le case e, ad esempio, l'uso di VNC ora non comporta inconvenienti. Il ping è leggermente diminuito, 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
--- 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
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
--- 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
Essere influenzato in gran parte dal ping elevato verso il VPS, che si aggira attorno ai 61.5 ms
Tuttavia, la velocità è aumentata notevolmente. 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 i risultati di iperf, mentre WireGuard l'ha "portata" fino a 5 Mbit/s.
Configurazione di WireGuard su VPS[Interfaccia]
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 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 di WireGuard su MK2 (da aggiungere 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 di WireGuard su MK3 (da aggiungere 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 il VPN di secondo livello, indico ai clienti di WireGuard la porta 51821. Teoricamente non è necessario, poiché il client stabilirà la connessione da qualsiasi porta non privilegiata disponibile, ma l'ho fatto in modo da 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 sia 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 all'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 usato easy-rsa.
Fonte: habr.com
