De ce un al doilea tunel VPN îl rupe pe primul?
Un al doilea client VPN instalează două semi-rute implicite și primul tunel se stinge: citește care rută câștigă, apoi separă după profil, tabel sau spațiu de nume.
Instalarea unui al doilea client VPN pentru a ajunge la o rețea de client este modul obișnuit în care începe asta, și primul tunel se stinge în timp ce ambii clienți raportează succes. Fiecare client a instalat o rută implicită, a doua era mai specifică, iar nucleul o urmează acum pentru tot, mai puțin propria conexiune exterioară a primului tunel. Nimic nu s-a prăbușit și niciun profil nu e greșit. O rută a înlocuit alta, iar soluția este să decizi care tunel ar trebui să dețină ruta implicită.
Simptomul: al doilea client câștigă în tăcere
OpenVPN: opțiunea redirect-gateway def1 nu suprascrie 0.0.0.0/0. Adaugă 0.0.0.0/1 și 128.0.0.0/1: împreună acoperă fiecare adresă IPv4, iar fiecare prefix bate o rută implicită simplă la lungime. Ruta implicită originală rămâne în tabel și nu mai este folosită pentru traficul obișnuit, iar o rută de gazdă către serverul VPN împiedică tunelul să-și prindă propriile pachete exterioare. Ambii clienți fac asta, iar al doilea își instalează pur și simplu perechea mai târziu.
De aceea primul tunel pare mort, nu deconectat. Interfața lui este sus, canalul de control este viu, și niciun trafic de aplicație nu mai ajunge la el. Plângerea inversă are același push lipsă: un telefon care se conectează dar nu trimite nimic vorbește de obicei cu un server care nu a anunțat niciodată redirect-gateway, așa că dispozitivul își păstrează propria rută implicită și ajunge doar la pool.
Fă o imagine a rutelor înainte și după ce se conectează al doilea client. Cele două semi-rute care apar în tabel sunt întreaga schimbare, și explică ambele plângeri. Nimic altceva din tabel nu trebuie să se miște pentru ca simptomul să apară. De aceea eliminarea celui de-al doilea client îl restaurează imediat pe primul.
Citește care tunel câștigă de fapt
Nu deduce câștigătorul din ordinea în care au pornit clienții sau din pictograma din tavă. Întreabă nucleul ce rută ar folosi pentru o destinație din afara ambelor rețele private, și citește interfața returnată.
ip route show
ip route get 198.51.100.24
route print -4
Find-NetRoute -RemoteIPAddress 198.51.100.24
Primele două sunt răspunsul Linux, iar ultimele două echivalentul Windows. Rulează-le cu ambele tuneluri sus, apoi deconectează unul și rulează-le din nou. Diferența dintre cele două ieșiri este faptul de care ai nevoie înainte de a alege o soluție, și durează mai puțin decât citirea jurnalului oricărui client.
Notează rezultatul, inclusiv numele interfeței și prefixul care s-a potrivit. Un tichet care spune că al doilea VPN l-a stricat pe primul este o descriere a simptomului, nu o afirmație de rutare pe care cineva să poată acționa. Căutarea îl transformă într-un fapt pe care următorul inginer îl poate reproduce cu o singură comandă.
Windows: împiedică un profil să dețină ruta implicită
Windows păstrează profiluri salvate, iar clientul integrat permite unuia să depindă de altul, astfel încât primul să urce automat când al doilea formează conexiunea. Profilul conectat cel mai recent tinde să păstreze ruta implicită, deci proprietarul practic este ultima conectare și nu prima. Dă fiecărui profil propriile rute push și activează split tunneling pentru cel care nu ar trebui să dețină ruta implicită.
Set-VpnConnection -Name "Contoso" -SplitTunneling $true
rasdial Contoso
Split tunneling schimbă asta: doar prefixele trimise de server ajung în tabel, ceea ce lasă ruta implicită la primul tunel. Designul tot eșuează dacă ambele servere trimit o rută implicită, pentru că atunci câștigă ultima conexiune și nicio setare din partea clientului nu schimbă asta. Repară push-ul pe partea serverului sau acceptă un singur proprietar.
Profilurile declanșate de aplicații sunt altă funcție și merită cunoscute: un profil Windows poate porni când se lansează un executabil numit, cu filtre de trafic care decid ce transportă. Este o setare de profil, nu o regulă de firewall, și rezolvă o problemă diferită de conflictul rutei implicite.
Linux: ține al doilea tunel în afara tabelului principal
Rularea a două instanțe openvpn --config pe o singură mașină pune ambii clienți în același tabel, iar trei opțiuni îi separă cu izolare crescândă. Cea mai ușoară este să împiedici complet al doilea client să editeze tabelul, cu route-nopull și rute explicite, sau un script route-up care instalează doar ce intenționezi. Atunci al doilea tunel poartă exact prefixele pe care le numești și nimic altceva. Atunci decizi tu ce prefixe merg unde, în loc să descoperi asta după aceea.
Rutarea pe politici este opțiunea de mijloc. O regulă selectează un tabel separat pentru o adresă sursă sau un marcaj de firewall, iar acel tabel poartă rutele celui de-al doilea tunel. Filtrarea căii inverse este capcana aici, pentru că un răspuns care sosește pe o interfață diferită de cea pe care tabelul ar alege-o este aruncat, așa că verifică setarea rp_filter înainte de a concluziona că tunelul este stricat.
ip rule add from 10.44.7.0/24 table 100
ip route add default dev tun1 table 100
sysctl net.ipv4.conf.all.rp_filter
Spațiile de nume de rețea sunt cea mai grea și cea mai curată opțiune. Pornește al doilea client în ip netns, dă-i o pereche veth și intră în acel spațiu de nume pentru a-l folosi. Interferența dispare pentru că fiecare spațiu de nume are propriile tabele în loc să împartă unul, ceea ce merită configurarea suplimentară când ambele tuneluri trebuie să rămână sus săptămâni.
Pe aplicație, și înlănțuirea ca problemă separată
Uneori doar un program ar trebui să folosească al doilea tunel. Pe Linux, rutarea pe politici după utilizator, cgroup sau port obține acel rezultat, iar o singură destinație poate fi fixată pe o interfață fără să atingă deloc ruta implicită. O aplicație care își fixează socketul pe o interfață nu consultă deloc tabelul de rutare, așa că un lansator poate continua să folosească adaptorul fizic până când o adresă este aleasă în propriile setări.
Înlănțuirea este o operație diferită de rularea a două tuneluri unul lângă altul. A înlănțuit peste B înseamnă că adresa serverului interior trebuie să fie accesibilă din interiorul tunelului exterior. Clientul exterior nu trebuie nici să confunde pachetele criptate ale clientului interior cu o scurgere. Un client într-o mașină virtuală este versiunea grosolană, dar fiabilă; ambele pe un singur host necesită munca de rutare de mai sus plus o cale exterioară către serverul interior care nu intră niciodată în tunelul interior.
Notează proprietarul rutei implicite, lista de prefixe purtate de fiecare tunel și calea DNS. Acele trei fapte transformă următorul incident într-o căutare în loc de o investigație.