Trecerea de la OpenVPN la WireGuard pentru unificarea rețelelor într-o rețea L2

Trecerea de la OpenVPN la WireGuard pentru unificarea rețelelor într-o rețea L2

Aș dori să împărtășesc experiența de unificare a rețelelor în trei apartamente geografic îndepărtate, fiecare dintre ele având routere cu OpenWRT ca gateway, într-o rețea comună. Când am ales metoda de unificare a rețelelor, am optat pentru L2 cu bridging, când toate nodurile rețelei se află în aceeași subrețea, în detrimentul L3 cu rutare de subrețele, deoarece aceasta oferă mai multe posibilități. Era planificat utilizarea transparentă a tehnologiilor Wake-on-Lan și DLNA în rețeaua creată.

Partea 1: Context

Protocolul ales pentru această sarcină a fost inițial OpenVPN, deoarece, pe de o parte, acesta poate crea un dispozitiv tap, care se integrează fără probleme într-un bridge, iar pe de altă parte, OpenVPN suportă funcționarea pe protocol TCP, ceea ce a fost important, deoarece în niciunul dintre apartamente nu era un IP dedicat. Nu am putut folosi STUN, deoarece providerul meu blochează intrările prin protocol UDP din rețelele sale, în timp ce protocolul TCP mi-a permis să redirecționez portul serverului VPN pe VPS-ul închiriat prin SSH. Da, această abordare creează o sarcină mai mare, deoarece datele sunt criptate de două ori, dar nu am dorit să includ VPS-ul în rețeaua mea privată, din cauza riscurilor de control din partea terților, deci faptul de a avea un astfel de dispozitiv în rețeaua de acasă era extrem de nedorit și am decis să plătesc pentru siguranță cu un overhead mai mare.

Pentru redirecționarea portului pe routerul pe care urma să fie desfășurat serverul, am folosit programul sshtunnel. Nu voi descrie detaliile configurației sale — este destul de simplu, doar menționez că sarcina sa era redirecționarea portului TCP 1194 de pe router pe VPS. Apoi, serverul OpenVPN a fost configurat pe dispozitivul tap0, care a fost introdus în bridge br-lan. Verificând conexiunea la serverul nou creat de pe laptop — a devenit clar că ideea de redirecționare a portului și-a justificat utilitatea și laptopul meu a devenit membru al rețelei routerului, deși fizic nu se afla în ea.

Ceea ce rămânea de făcut era să distribui IP-urile în diferitele apartamente astfel încât să nu existe conflicte și să configurez routerele ca clienți OpenVPN.
Au fost selectate următoarele adrese IP ale routerelor și intervalele serverelor DHCP:

  • 192.168.10.1 cu intervalul 192.168.10.2 — 192.168.10.80 pentru server
  • 192.168.10.100 cu intervalul 192.168.10.101 — 192.168.10.149 pentru routerul din apartamentul nr. 2
  • 192.168.10.150 cu intervalul 192.168.10.151 — 192.168.10.199 pentru routerul din apartamentul nr. 3

De asemenea, a fost necesar să alocăm aceste adrese pentru routerele client OpenVPN-server, prin adăugarea în configurația sa a liniei:

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

și adăugând următoarele linii în fișierul /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

unde flat1_id și flat2_id sunt numele dispozitivelor menționate la crearea certificatelor pentru conectarea la OpenVPN

În continuare, pe routere au fost configurate clienți OpenVPN, dispozitive tap0 fiind incluse în podul br-lan. La acest stadiu părea că totul era în regulă, deoarece toate cele trei rețele se vedeau între ele și funcționau ca un întreg. Cu toate acestea, a apărut un detaliu neplăcut: uneori dispozitivele puteau primi o adresă IP de la un alt router, cu toate consecințele care decurgeau. Dintr-un motiv oarecare, routerul dintr-unul din apartamente nu reușea să răspundă la timp la DHCPDISCOVER și dispozitivul primea o adresă greșită. Am realizat că trebuie să filtrez aceste cereri în tap0 pe fiecare dintre routere, dar, așa cum s-a dovedit, iptables nu poate funcționa cu un dispozitiv care este parte a unui pod și trebuia să apeleze la ebtables. Din păcate, nu l-am găsit în firmware-urile mele și a trebuit să recompun imaginile pentru fiecare dispozitiv. Fiindcă am făcut asta și am adăugat aceste linii în /etc/rc.local al fiecărui router, problema a fost rezolvată:

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

Această configurație a existat timp de trei ani.

Partea 2: Întâlnirea cu WireGuard

În ultima vreme, pe internet s-a vorbit din ce în ce mai mult despre WireGuard, admirând simplitatea configurării sale, viteza de transfer ridicată și latența scăzută, în condiții de siguranță comparabilă. Căutând informații suplimentare despre el, am înțeles că nici funcționarea ca membru al podului, nici funcționarea prin protocolul TCP nu sunt susținute, ceea ce m-a făcut să cred că nu am alternative la OpenVPN. Astfel, am amânat întâlnirea cu WireGuard.

Cu câteva zile în urmă, pe resursele legate de IT a circulat vestea că WireGuard va fi în sfârșit inclus în kernelul Linux, începând cu versiunea 5.6. Articolele de știri, ca de obicei, l-au lăudat pe WireGuard. M-am adâncit din nou în căutarea unor alternative la vechiul și bunul OpenVPN. De data aceasta, am dat peste acest articol. Acesta vorbea despre crearea unui tunel Ethernet peste L3 folosind GRE. Articolul mi-a dat speranță. Rămânea neclar ce să fac cu protocolul UDP. Căutările mă duceau la articole despre utilizarea socat împreună cu un tunel SSH pentru a redirecționa un port UDP, totuși, în acestea se menționa că această abordare funcționează doar în modul unei singure conexiuni, ceea ce ar face imposibilă funcționarea mai multor clienți VPN. Mi-a venit ideea de a ridica un server VPN pe VPS, iar pentru clienți să configurez GRE, dar, după cum s-a dovedit, GRE nu suportă criptarea, ceea ce ar însemna că, în cazul în care un terț ar obține acces la server, acesta ar avea întreaga trafic între rețelele mele, lucru care nu m-ar mulțumi deloc.

Din nou, am decis să optez pentru criptare redundantă, folosind VPN peste VPN conform următoarei scheme:

VPN de nivelul întâi:
VPS este serverul cu adresa internă 192.168.30.1
MC este client VPS cu adresa internă 192.168.30.2
MK2 este client VPS cu adresa internă 192.168.30.3
MK3 este client VPS cu adresa internă 192.168.30.4

VPN de nivelul doi:
MC este serverul cu adresa externă 192.168.30.2 și internă 192.168.31.1
MK2 este client MC cu adresa 192.168.30.2 și are IP intern 192.168.31.2
MK3 este client MC cu adresa 192.168.30.2 și are IP intern 192.168.31.3

* MC — router-server în apartamentul 1, MK2 — router în apartamentul 2, MK3 — router în apartamentul 3
* Configurațiile dispozitivelor sunt publicate într-un spoiler la sfârșitul articolului.

Așadar, ping-urile între nodurile rețelei 192.168.31.0/24 funcționează, este timpul să trecem la configurarea tunelului GRE. Înainte de aceasta, pentru a nu pierde accesul la routere, este bine să configurăm tuneluri SSH pentru a redirecționa portul 22 pe VPS, astfel încât, de exemplu, pe portul 10022, VPS-ul să fie accesibil routerului din apartamentul 2, iar pe portul 11122, VPS-ul să fie accesibil routerului din apartamentul 3. Configurarea redirecționării este cel mai bine să fie realizată tot cu sshtunnel, deoarece acesta va restaura tunelul în caz de cădere.

Tunelul este configurat, se poate conecta la SSH prin portul redirecționat:

ssh root@MOUL_VPS -p 10022

Apoi, trebuie să dezactivăm OpenVPN:

/etc/init.d/openvpn stop

Acum vom configura tunelul GRE pe routerul din apartamentul 2:

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

Și vom adăuga interfața creată în pod:

brctl addif br-lan grelan0

Procedura similară se va efectua pe routerul-server:

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

Și, de asemenea, vom adăuga interfața creată în pod:

brctl addif br-lan grelan0

Începând de acum, ping-urile încep să funcționeze cu succes în noua rețea și mă îndrept cu satisfacție spre o cafea. Apoi, pentru a evalua cum funcționează rețeaua la celălalt capăt al firului, încerc să mă conectez prin SSH la unul dintre calculatoarele din apartamentul 2, dar clientul SSH "se blochează", fără a-mi oferi posibilitatea de a introduce parola. Încerc să mă conectez la acest computer prin telnet pe portul 22 și văd o linie din care pot înțelege că conexiunea se stabilește, serverul SSH răspunde, pur și simplu dintr-un anumit motiv nu îmi oferă acces.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Încerc să mă conectez la el și prin VNC și văd un ecran negru. Îmi spun că este vina computerului de la distanță, deoarece mă pot conecta fără probleme la routerul din acest apartament, folosind adresa internă. Totuși, decid să mă conectez la SSH-ul acestui computer prin router și cu surprindere descopăr că conexiunea reușește, iar computerul remote funcționează perfect, dar de asemenea nu se poate conecta la computerul meu.

Scot dispozitivul grelan0 din pod și pornesc OpenVPN pe routerul din apartamentul 2, asigurându-mă că rețeaua funcționează din nou așa cum trebuie și conexiunile nu se întrerup. Căutând, mă lovesc de forumuri unde oamenii se plâng de probleme similare, unde li se recomandă să crească MTU. Se spune, se face. Totuși, până când MTU nu a fost setat suficient de mare — 7000 pentru dispozitivele gretap, au fost observate fie întreruperi ale conexiunilor TCP, fie o viteză de transfer scăzută. Datorită MTU înalt pentru gretap — MTU pentru conexiunile WireGuard de primul și al doilea nivel au fost setate la 8000 și 7500 respectiv.

Am realizat o configurație similară și pe routerul din apartamentul 3, cu singura diferență că routerul-server a adăugat o a doua interfață gretap numită grelan1, care a fost de asemenea adăugată în podul br-lan.

Totul funcționează. Acum putem adăuga configurarea gretap la pornirea automată. Pentru asta:

Am adăugat aceste linii în /etc/rc.local pe routerul din apartamentul 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

Am adăugat acest lucru în /etc/rc.local pe routerul din apartament 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

Și pe routerul-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

După repornirea routerelor clienților, am descoperit că dintr-un motiv oarecare nu se conectează la server. Conectându-mă la SSH (noroc că am configurat dinainte sshtunnel pentru aceasta) am observat că WireGuard creează, fără motiv, o rută pentru endpoint, dar incorectă. Astfel, pentru 192.168.30.2, în tabela de rutare era specificată o rută prin interfața pppoe-wan, adică prin internet, deși ruta către acesta ar fi trebuit să fie direcționată prin interfața wg0. După ștergerea acestei rute, conexiunea s-a restabilit. Nu am reușit să găsesc instrucțiuni despre cum să fac ca WireGuard să nu creeze aceste rute. Mai mult decât atât, nu am înțeles dacă este o particularitate a OpenWRT sau a WireGuard. Fără să stau prea mult să investighez această problemă, am adăugat pe ambele routere într-un script, care rulează ciclic, o linie care șterge această rută:

route del 192.168.30.2

În concluzie

Nu am reușit să renunț complet la OpenVPN, deoarece trebuie uneori să mă conectez la o rețea nouă de pe laptop sau telefon, iar configurarea unui dispozitiv gretap pe acestea în general este imposibilă, însă, în ciuda acestui lucru, am obținut un avantaj în viteza de transfer de date între apartamente, iar utilizarea VNC acum nu mai provoacă neplăceri. Pingul s-a redus nesemnificativ, dar a devenit mai stabil:

Când folosesc 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

Când folosesc 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

Acesta este influențat în principal de pingul ridicat către VPS, care este de aproximativ 61.5 ms

Însă, viteza a crescut semnificativ. Astfel, în apartamentul cu router-server am o viteză de conexiune la Internet de 30 Mbit/s, iar în celelalte apartamente câte 5 Mbit/s. În același timp, în timpul utilizării OpenVPN nu am reușit să ating o viteză de transfer de date între rețele mai mare de 3,8 Mbit/s conform măsurătorilor iperf, în timp ce WireGuard a „împins” aceasta la aceleași 5 Mbit/s.

Configurarea WireGuard pe VPS[Interface]
Adresa = 192.168.30.1/24
PortAscultare = 51820
CheiePrivată =

[Peer]
PublicKey =
AllowedIPs = 192.168.30.2/32

[Peer]
PublicKey =
AllowedIPs = 192.168.30.3/32

[Peer]
PublicKey =
AllowedIPs = 192.168.30.4/32

Configurarea WireGuard pe MS (adăugată în /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'

Configurarea WireGuard pe MK2 (adăugată în /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'

Configurarea WireGuard pe MK3 (adăugată în /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'

În configurațiile descrise pentru VPN de nivel secundar, indic clienților WireGuard portul 51821. Teoretic, acest lucru nu este necesar, deoarece clientul se va conecta de la orice port liber neprivilegiat, dar am făcut astfel încât să pot interzice toate conexiunile intrante pe interfețele wg0 ale tuturor routerelor, cu excepția conexiunilor UDP intrante pe portul 51821.

Sper că articolul va fi util cuiva.

P.S. De asemenea, vreau să împărtășesc scriptul meu, care îmi trimite o notificare PUSH pe telefon în aplicația WirePusher, atunci când în rețeaua mea apare un nou dispozitiv. Iată linkul la script: github.com/r0ck3r/device_discover.

UPDATE: Configurarea serverului OpenVPN și a clienților

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

Client OpenVPN

client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Schimbați cu IP-ul extern al routerului dvs.
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

Am folosit easy-rsa pentru a genera certificatele

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster