Հոսթի տրաֆիկի երթուղումը VPN-ով VM-ում՝ վեց ստուգում
Վեց հաջորդական ստուգում՝ VM-ը VPN դարպաս դարձնելու համար, որով երթուղվում է նրա սեփական հոսթի տրաֆիկը՝ ադապտերի ռեժիմ, փոխանցում, NAT, հոսթի մարշրուտներ, DNS, MTU։
Վեց ստուգում, հաջորդաբար կատարված, որոշում են՝ արդյոք VM-ը կարող է լինել VPN դարպաս իր սեփական հոսթի համար։ Հիպերվիզորը ձեզ համար այս ոչինչ չի անում՝ թունելը պատկանում է հյուրին, մարշրուտը՝ հոսթին, իսկ նրանց միջև ցանցը սովորական երթուղում է։ Ես պահում եմ այս ցանկը, որովհետև մեկ քայլ բաց թողնելը միշտ տալիս է նույն ախտանիշը՝ լռություն, երբ հոսթը ուրախ ping է անում հյուրին և չի հասնում ոչ մի ներքին բանի։
Սկսեք պատճառից։ Կամ կորպորատիվ կլիենտը տեղադրվում է միայն հյուրի ներսում, կամ քաղաքականությունը պահում է այն այնտեղ, և ձեզ դեռ պետք է ներքին build սերվերը հոսթից։ Եթե հոսթին թույլատրվում է սեփական կլիենտ, արեք դա փոխարենը՝ հոսթի վրա մեկ թունելը միշտ հաղթում է երկու ցանցին գումարած NAT-ին։
Ստուգում 1: հոսթին պետք է կապ, որին կարող է հասցե տալ
Հոսթը պետք է ունենա ինտերֆեյս հյուրի երկրորդ ադապտերի նույն պրեֆիքսում։ VirtualBox-ում host-only, VMware Workstation-ում host-only կամ հատուկ VMnet, QEMU/KVM-ում ներքին կամուրջ կամ tap սարք, և Hyper-V-ում Internal switch՝ բոլորը համապատասխանում են։ Հյուր 192.168.56.2, հոսթ 192.168.56.1, պրեֆիքս 192.168.56.0/24 այն դասավորությունն է, որ օգտագործում եմ լաբորատորիաներում։
QEMU-ի օգտատիրոջ ռեժիմի ցանցը (-netdev user, լռելյայն SLIRP backend) և VirtualBox-ի NAT-ը լիովին ձախողում են այս ստուգումը։ Հյուրի փաթեթները հասնում են հոսթի վրա պրոքսի պրոցեսի, այնպես որ հոսթը երբեք չի տեսնում հյուրի հասցեները կրող սարք և չունի ինչի վրա մարշրուտ ցույց տա։ Hyper-V-ի Default Switch-ը նույն պատմությունն է։ Եթե հոսթից ping 192.168.56.2-ը ձախողվում է, կանգ առեք՝ ավելի ուշ ավելացված ոչ մի մարշրուտ դա չի շտկի։
Ստուգում 2: հյուրը փոխանցում և թարգմանում է
Հոսթից եկող փաթեթները գալիս են host-only աղբյուրի հասցեով և ներքին նպատակակետով, ուստի հյուրը պետք է դրանք փոխանցի և հետո թաքցնի իր թունելի հասցեի հետևում, և Linux հյուրում դա նշանակում է փոխանցում, FORWARD accept զույգ և source NAT դեպի թունել։
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT
sudo iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o tun0 -j MASQUERADE
MASQUERADE կանոնը այն մասն է, որը մարդիկ բաց են թողնում։ Կորպորատիվ երթուղիչները հազվադեպ գիտեն, որ 192.168.56.0/24 կա, իսկ կանոնի հետ ներքին սերվերները տեսնում են հյուրի թունելի հասցեն ու պատասխանում դրան, և պատասխանը ճանապարհ է գտնում հետ դեպի հյուր։
Windows հյուրը ավելի անշնորհք է։ IPEnableRouter=1-ը SYSTEM\CurrentControlSet\Services\Tcpip\Parameters-ի տակ միացնում է փոխանցումը առանց թարգմանության, ուստի այն աշխատում է միայն այնտեղ, որտեղ կորպորատիվ երթուղումն արդեն հետ է ցույց տալիս ձեր host-only պրեֆիքսին։ Internet Connection Sharing-ը թարգմանում է, բայց վերահամարակալում է համօգտագործվող ադապտերը 192.168.137.1-ի, ուստի կարդացեք այն հասցեն, որն այն իրականում վերցրել է, նախքան հոսթի մարշրուտներ գրելը։
Ստուգում 3: հոսթի մարշրուտները նշում են հյուրին, ոչ թունելը
Հյուրի միջով ուղարկեք միայն այն պրեֆիքսները, որոնք անհրաժեշտ են հոսթին, իսկ Linux-ում մեկ մարշրուտ մեկ պրեֆիքսի համար բավական է և մաքուր շրջվում է։
sudo ip route add 10.20.0.0/16 via 192.168.56.2
ip route get 10.20.30.40
Windows-ում համարժեքը route add 10.20.0.0 mask 255.255.0.0 192.168.56.2-ն է։ Փորձարկելիս թողեք -p-ը դուրս, որպեսզի վատ մարշրուտը մահանա վերագործարկման ժամանակ, և ավելացրեք այն, երբ ուղին աշխատի, մի հեռացրեք հոսթի լռելյայն մարշրուտը, եթե հոսթի բոլոր հավելվածները թունելով չպետք է անցնեն, և եթե իսկապես ամբողջական թունել է պահանջվում, ավելացրեք երկու /1 մարշրուտները և պահեք ուղիղ մարշրուտը դեպի հիպերվիզորի ցանցը։
sudo ip route add 0.0.0.0/1 via 192.168.56.2
sudo ip route add 128.0.0.0/1 via 192.168.56.2
Windows հոսթում ստուգեք նաև ինտերֆեյսի մետրիկը։ Մարշրուտը, որն ավելացվել է, երբ host-only ադապտերը անջատված էր, մնում է աղյուսակում, բայց երբեք տրաֆիկ չի կրում, և ավելի ցածր մետրիկով երկրորդ ադապտերը կարող է հաղթել նույն պրեֆիքսի որոնումը։
Ստուգում 4: DNS-ը հետևում է մարշրուտին, ոչ թունելի լռելյայնին
Մարշրուտները տեղափոխում են փաթեթներ, լուծիչը որոշում է, թե որ անուններն են փաթեթներ ստեղծում։ Սահմանափակեք կորպորատիվ լուծիչը կորպորատիվ գոտով՝ հոսթի լուծիչը փոխարինելու փոխարեն, և ուղղեք այն DNS սերվերին, որին նոր մարշրուտն արդեն հասնում է, ինչպես հոսթի վրա systemd-resolved-ի դեպքում։
resolvectl dns eth1 10.20.0.53
resolvectl domain eth1 '~corp.example.com'
Windows-ում անունների լուծման քաղաքականության աղյուսակի գրառումը նույն աշխատանքն է անում՝ Add-DnsClientNrptRule -Namespace ".corp.example.com" -NameServers 10.20.0.53։ Եթե հյուրը գործարկում է իր լուծիչը host-only հասցեի վրա, օգտագործեք այդ հասցեն փոխարենը, բայց միայն այն բանից հետո, երբ հաստատեք, որ այն պատասխանում է 192.168.56.2-ի վրա, այլ ոչ loopback-ի։
Ապա ստուգեք MTU-ն, նախքան DNS-ին մեղադրելը դանդաղ էջերի համար։ Թունելի ինտերֆեյսը փոքր է հոսթի 1500 բայթ ինտերֆեյսից, ուստի DF բիթը դրած ամբողջ չափի սեգմենտներ ուղարկող հոսթը դրանք կորցնում է հյուրի ներսում ինչ-որ տեղ։ Դասական ախտանիշն աշխատող ping-ն է և ներքին վեբ հավելվածը, որը կանգ է առնում TLS ձեռքսեղմումից հետո, այնպես որ սեղմեք MSS-ը հյուրի փոխանցման ուղում։
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Ստուգում 5: ստուգեք երկու ծայրերից
Հոսթից traceroute-ը կամ tracert-ը դեպի ներքին հասցե պետք է ցույց տա 192.168.56.2-ը որպես առաջին hop, ոչ թե ֆիզիկական դարպասը։ Հյուրում դիտեք նույն փորձի ելքը՝ tcpdump -ni any host 10.20.30.40-ը ցույց է տալիս փոխանցված հարցումը host-only կողմում և թարգմանվածը թունելում։ Հարցումը, որը դուրս է գալիս, վերադառնում և այնուամենայնիվ հոսթին լուռ է թողնում, մատնանշում է վերադարձի ուղին։
Երկու ձախողում բացատրում են դրա մեծ մասը։ Կամ հյուրի թունելը վերադարձի մարշրուտ չի կրում host-only պրեֆիքսի համար, որովհետև NAT կանոնը բացակայում է, կամ հոսթի մարշրուտը ցույց է տալիս հասցեի, որը հյուրը վերագործարկումից հետո այլևս չունի։ Կրկին կարդացեք հասցեները ip -br addr-ով և ip route get-ով՝ նախորդ նստաշրջանի գրառումներին վստահելու փոխարեն։
Ստուգում 6: դարձրեք այն դիմացկուն վերագործարկման և հիպերվիզորի արդիականացման նկատմամբ
Պահպանեք երկու կեսերը՝ netplan կամ NetworkManager մարշրուտի կազմաձևում հոսթի վրա, route add ... -p Windows-ում, և net.ipv4.ip_forward=1-ը /etc/sysctl.d/-ում՝ գումարած firewall-ի կանոնների հավաքածու, որը վերաբեռնվում է հյուրում։ Արեք հյուրի snapshot-ը հենց որ կազմաձևը ստուգվի, նախքան կորպորատիվ կլիենտի հաջորդ թարմացումը կհասնի։
Host-only ցանցերը վերահամարակալվում են, երբ հիպերվիզորը վերստեղծում է իր ադապտերները, ինչը լուռ անվավեր է դարձնում 192.168.56.0/24-ի վրա կառուցված յուրաքանչյուր մարշրուտ և NAT կանոն։ Արդիականացումից հետո կրկնեք առաջին երեք ստուգումները հերթով, դա մեկ րոպե է տևում և բռնում է այն դեպքը, երբ հոսթը դեռ ունի իր մարշրուտը, մինչ հյուրը տեղափոխվել է նոր ենթացանց։
IPv6-ը պահանջում է իր առանձին անցում։ ip6tables կանոնները, AAAA գրառումները և հոսթի մարշրուտների երկրորդ ընտանիքը չեն հետևում IPv4-ի կարգավորմանը, և IPv6-ով հասանելի կորպորատիվ ծառայությունը մշտապես կոտրված կթվա, մինչ IPv4-ը աշխատում է։
Անցավ թե ոչ, հերթով՝ հոսթը կարող է ping անել հյուրի host-only հասցեին, հյուրը փոխանցում և MASQUERADE է անում դեպի թունել, ip route get-ը վերադարձնում է հյուրին որպես դարպաս ներքին պրեֆիքսի համար, կորպորատիվ անունները լուծվում են սահմանափակ լուծիչով, traceroute-ը ցույց է տալիս հյուրին առաջինը, և նույն վեց պատասխանները դիմանում են վերագործարկմանը։