Traficul Docker și VM în spatele OpenVPN: rutare sau renumerotare?
Containerele și oaspeții de pe un host cu client OpenVPN fie pierd calea de întoarcere, fie se ciocnesc cu prefixul tunelului. Trei întrebări aleg soluția.
Hostul navighează prin tunel, iar containerul de lângă el nu ajunge nicăieri. Publicarea unui port dintr-un container care rulează propriul client VPN este mai rău: cererea ajunge, iar răspunsul nu pleacă niciodată. Ambele sunt decizii de rutare pe host, iar Docker este doar mesagerul.
Trei întrebări stabilesc care dintre cele două cazuri este în fața ta și durează aproximativ un minut.
Două defecțiuni care arată la fel
Prima este o problemă a căii de întoarcere. Portul publicat este tradus în container, cererea ajunge, iar răspunsul este rutat prin ruta implicită a hostului, pe care clientul OpenVPN a îndreptat-o spre tun0. Răspunsul pleacă de la o adresă pe care partenerul îndepărtat nu o așteaptă și este aruncat. A doua este o coliziune de prefixe: puntea implicită a Docker deține 172.17.0.0/16, iar un tunel corporativ împinge același interval.
Una se repară cu o tabelă de rutare, cealaltă prin renumerotarea unei punți. Editarea înainte de a ști care este care este modul de a strica un container funcțional.
Decide cu trei întrebări
Întrebarea unu: dispare defecțiunea când oprești VPN-ul? Dacă totul funcționează cu tunelul oprit, suspectează calea de întoarcere. Întrebarea doi: ip route show table all listează același prefix de două ori, o dată pe o punte și o dată pe tun0? Aceasta este coliziunea. Întrebarea trei: adresa afectată este un container, un oaspete NAT sau un oaspete în punte?
A treia întrebare contează pentru că fiecare are o altă soluție corectă, iar aplicarea soluției pentru container la un oaspete libvirt irosește o seară.
ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'Calea de întoarcere: o tabelă pentru o singură adresă sursă
Când traficul containerului trebuie să iasă prin interfața fizică în timp ce hostul însuși folosește tunelul, rutarea bazată pe sursă este cea mai mică schimbare. Adaugă o regulă care se potrivește cu adresa containerului și trimite-o într-o tabelă dedicată. Nimic altceva pe host nu se mișcă.
ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10Fiecare pachet a cărui sursă este acea adresă consultă mai întâi tabela 10, iar tabela 10 îl trimite la gateway-ul punții în loc de tunel.
Verifică cu ip route get 1.1.1.1 from 172.22.0.3. Răspunsul trebuie să numească interfața punții, nu tun0. Regulile adăugate astfel dispar la repornire, așa că pune-le în unit sau în cârligul de rețea care deține containerul.
Același tipar funcționează pentru un container WireGuard, unde și calea de răspuns are nevoie de o regulă explicită.
Coliziune de prefixe: renumerotează puntea
O tabelă de rutare trimite un prefix într-un singur loc. Dacă VPN-ul împinge 172.17.0.0/16 în timp ce puntea Docker este deja acolo, câștigă metrica mai mică: Docker instalează ruta conectată cu metrica 0, iar ruta împinsă ajunge cu 50. Atunci tunelul pare stricat în timp ce Docker continuă să funcționeze, sau invers, în funcție de ordinea instalării. Renumerotează puntea în loc să te lupți cu metrica.
{
"bip": "10.200.0.1/24",
"default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}Repornește Docker după modificare și recreează rețelele construite cu vechiul pool. Schimbarea metricii doar mută conflictul la următoarea pornire.
VM-urile au nevoie din nou de alt răspuns
Un oaspete libvirt în rețeaua NAT implicită moștenește rutarea hostului și nu mai ajunge afară odată ce tunelul hostului deține ruta implicită. Trecerea oaspetelui pe un dispozitiv în punte sau macvtap îi dă propria cale în rețeaua fizică. În virt-manager adaugă hardware, alege Network, setează sursa pe dispozitivul host macvtap, păstrează virtio ca model, apoi dezactivează vechea interfață NAT.
Un oaspete macvtap de obicei nu poate ajunge la propriul host. Acesta este un comportament așteptat, nu o defecțiune, și își are locul în nota pe care o lași.
Pentru un oaspete care are nevoie doar de LAN-ul hostului, clientul furnizorului poate avea comutatorul lipsă: cu Mullvad, mullvad lan set allow restabilește accesibilitatea locală fără a atinge libvirt. Iar când un container trebuie să fie accesibil doar prin tunel, leagă portul publicat de adresa tunelului, -p 10.8.0.5:8080:8080, în loc să îl publici pe fiecare adresă.