VPN клиенті қосылады, браузер жұмыс істейді, ал шын мәнінде маңызды сол бір команда әлі де үй байланысыңыз арқылы шығады. Немесе керісінше болады: туннель әдепкі маршрутты алып, жергілікті файл сервері жұмыс үстелінен жоғалады. Мен мұны ішкі артефакт айнасына жетуі керек болған құрастыру агентінде кездестірдім, ал хосттың қалғаны кеңсе LAN-ында қалды, және клиент дәл екі таңдау ұсынды: бүкіл трафик немесе ештеңе. Екі бағыттағы сұраныс бірдей, осы бағдарлама, бүкіл машина емес, және көптеген клиенттерде бұл үшін құсбелгі жоқ, өйткені маршрут кестесі бағдарламаның не екенін ешқашан білмеген.

Неге маршрут кестесі сіздің бағдарламаңызды көре алмайды

Процесс пакет жібергенде, стек маршрут кестесінен барар мекенжайды іздейді. Орындалатын файлдың атауы да, порт та бұл іздеуге кірмейді. Домен атаулары да сол себептен сәтсіз болады: туннель трафикті мекенжайға апарады, ал атау мекенжайға айналған кезде маршруттау ядрода қалған жалғыз тұтқа болады. Сондықтан «VPN тек осы сайт үшін» ақыр соңында проксиді білдіреді, ал «VPN тек осы бағдарлама үшін» шағын механизмдер жиынтығының бірін білдіреді.

MechanismWhat selectsCoversOn tunnel drop
Socket bindsource addressa client you controlconnections fail
UID rule (Linux)owning userevery process of one accountconnections fail
Firewall profile (Windows)adapter profileone programfails closed
Network namespacenamespace membershipeverything started insideconnections fail
SOCKS hopapp proxy settingone app or one browser profileconnections fail

Бұлардың ешқайсысы процесс бойынша маршрут емес. Әрқайсысы шешімді бағдарламаны, пайдаланушыны немесе қолданбаның өз конфигурациясын көретін қабатқа жылжытады.

Бір ғана межелі орын әлі де маршрут, бағдарлама ережесі емес. macOS-те әдеттегі әдіс «Барлық трафикті VPN арқылы жіберу» белгісін алып тастау және хост маршрутын қосу: sudo route add -host internal-tuner.example -interface ppp0, ол қайтадан sudo route delete -host internal-tuner.example -interface ppp0 арқылы жойылады. Алдымен ifconfig ішінен интерфейс атауын оқыңыз, өйткені ppp0 тек мысал. Хост маршрутында алмастырғыш таңбалар жұмыс істемейді, сондықтан бірнеше атпен сөйлесетін қызметке әр ат үшін бір жазба керек, және ереже машинадағы әр процесті қамтиды, сіз ойлаған процесті емес.

Сокетті туннель мекенжайына байлаңыз

Клиентті өзіңіз басқарсаңыз, байлау ең арзан таңдаушы. Туннельдің жергілікті мекенжайына байланған сокет сол интерфейс арқылы шығады, егер онда межелі орынға маршрут болса, ал машинадағы қалғанның бәрі әдеттегі жолын сақтайды. Тондылық — байлау бастау мекенжайын таңдайды, ал маршрут кестесі әлі де шығуды таңдайды. Байлау жалғыз өзі туннельге маршруты жоқ трафикті жылжытпайды, және «байладым, бірақ әлі де дұрыс емес жақтан шығады» деген шағымдардың көбінің артында осы қате тұр.

import socket
s = socket.socket()
s.bind(("10.8.0.2", 0))
s.connect(("build.internal.example", 443))

Жоғары деңгейлі құралдар сол идеяны ұсынады: curl --interface 10.8.0.2, PHP-де CURLOPT_INTERFACE және Python-ның HTTP клиенттеріндегі source_address аргументі. Мекенжай туннельге тиесілі болуы керек, және мұндағы қате маршруттау шағымы ретінде емес, қарапайым байланыс қатесі ретінде сәтсіз аяқталады. Мекенжайдың орнына құрылғы атауына байлау — Linux артықшылығы және Windows немесе macOS-қа өтпейді, сондықтан тасымалданатын скрипттер мекенжайды береді.

Linux: иесін сәйкестендіріңіз, бағдарлама атауын емес

Ядро сокеттің иесін сәйкестендіре алады, сондықтан бөлек есептік жазба таңдаушыға айналады. Туннельді өз маршрут кестесіне қойып, оған тек сол есептік жазбаның трафигін жіберіңіз:

ip rule add uidrange 1001-1001 lookup 100
ip route add default dev tun0 table 100

Бұл туннель әлдеқашан әдепкі маршрут болмаса ғана жұмыс істейді. Клиентті --route-nopull арқылы іске қосыңыз, немесе --pull-filter ignore "redirect-gateway" арқылы OpenVPN 2.4 және одан жаңа нұсқаларында итерілген қайта бағыттауды сүзіңіз, содан кейін кесте жазбасын өзіңіз қосыңыз. Әйтпесе екі әдепкі де бар және басымдығы төмені жеңеді. Оның әдейі жасалған нұсқасы — әдепкі маршрутты туннель шлюзіне бағыттау немесе мұны ажырату скриптінен жасау: туннель құлағанда трафикті интернеттен тыс ұстайды, бірақ бұл өшіру ажыратқышы, таңдаушы емес, және біреу оны жойғанша қалады.

Күштірек нұсқа — желілік атаулар кеңістігі. Оны жасаңыз, клиентті ішінде іске қосыңыз және қолданбаны ip netns exec арқылы қосыңыз. Атаулар кеңістігінен тыс ешнәрсе туннель интерфейсін көрмейді, сондықтан қолданба кездейсоқ хост маршрутына қайта алмайды. Құны нақты: кеңістікке физикалық желіге жету үшін veth жұбы және өз шешуші файлы керек, өйткені тіркеу атаулар кеңістігі хосттың шешу параметрлерін бөліспейді.

Екі ақау режимі ағудың көбін түсіндіреді. Атауларды шешу әлі де хосттың шешушісінде болады, сондықтан TCP байланысы ішке кірсе де, сұраныс туннельден тыс шығады. Ал IPv6-ға өз ip -6 rule керек, өйткені v4 ережесі оны қамтымайды.

Windows және macOS: файрволды шектеңіз немесе прокси беріңіз

Windows-та да қолданба бойынша маршрут таңдаушы жоқ, бірақ оның файрвол ережелерін профильге шектеуге болады, ал VPN адаптерін «жария» деп жіктеуге болады, үй LAN-ы «жеке» болып қалады. Бағдарлама үшін «жеке» және «домен» профильдерінде шығыс блоктау ережелерін жасаңыз, «жарияны» ашық қалдырыңыз, сонда қолданба желіге тек туннель арқылы жетеді. Алдымен байланыстың желілік санатын орнатыңыз, содан кейін ереженің файрвол мониторы тақтасында сәйкес келгенін растаңыз. Бұл бөгеу, маршрут емес: туннель құлағанда жабық күйде сәтсіз болады, және файрволды елемейтін қолданбаны тоқтата алмайды.

macOS басқа құралдармен сол логиканы ұстанады. SSH арқылы жететін SOCKS тыңдаушысы ең аз араласатын нұсқа, өйткені ssh -D 1080 user@host бір жергілікті порт жасайды және оны пайдалануға конфигурацияланған қолданбалар ғана сол жолмен жүреді. pf ережесі бағдарламаны пайдаланушы немесе топ бойынша бөгей алады, бірақ әлі де тек сол бағдарлама үшін туннельді таңдай алмайды. Tunnelblick домен бойынша мүлдем сүзе алмайды, өйткені маршруттар мекенжайлармен жұмыс істейді; OpenConnect пайдаланушылары сервер тым кең префикстер тізімін итергенде vpn-slice-ке жүгінеді.

Екі айналып өту платформа құралдары өткізіп жіберетін нәрсені жабады. Проксиді домен бойынша ауыстыратын браузер кеңейтімдері «тек осы сайт» үшін практикалық жауап, өйткені олар атаулар әлі бар қолданба қабатында әрекет етеді; олар бір браузерді жабады, басқа ештеңені емес. Дөрекі әдіс — жеткізушінің клиентін виртуалды машинада жүргізу, сонда қонақ маршрут өзгерісіне ие болады, ал хост өз жолын сақтайды, екі желілік стекті күту құнымен.

Байлау мүмкіндігі жоқ құралдарға арналған SOCKS секірісі

Көптеген қолданбаны интерфейстер туралы ештеңе білмесе де, HTTP немесе SOCKS проксиіне бағыттауға болады. SSH клиенті сервер жағында ешбір өзгеріссіз біреуін ұсынады:

ssh -N -D 127.0.0.1:9999 [email protected]

Сол портты пайдалануға конфигурацияланғанның бәрі бастионда шығады, ал үстелдің қалғаны әдеттегі байланысын сақтайды. Туннель мекенжайына байланған жергілікті 3proxy данасы SSH-сыз бір порт үшін дәл солай істейді, ал stunnel TLS-ке оралған бір портты жабады. Шектеулер практикалық: прокси тек оны пайдалануды білетін протоколдарды тасиды, UDP-ге SOCKS5 UDP бірлестігі керек, оны көптеген клиенттің «SOCKS5» параметрі қоспайды, және DNS прокси арқылы шешілуі керек (curl-де socks5h), әйтпесе атау жергілікті шешушіге ағады.

Тыңдаушыны жергілікті ілмекте ұстаңыз, басқа машинаға керек болмаса.

Жолды күй хабарламасымен емес, ұстап алумен тексеріңіз

Қолданбаның күй терезелері параметрді сипаттайды, пакетті емес. Екі интерфейсте де ұстап алып, салыстырыңыз:

tcpdump -i any -n port 443
ss -tnp | grep 443

Егер байланыс физикалық интерфейсте көрініп, туннельде сәйкес жазба болмаса, клиент не деп хабарласа да, таңдаушы күшінде емес. IPv6 мен шешушіні бөлек тексеріңіз, және көмекші процесс немесе мұраланған жүйелік прокси сияқты екінші жолдың бар-жоғын тексеріңіз.

Содан кейін талапқа сай шекараны таңдаңыз: бір сайтқа прокси жетеді, бір есептік жазбаға UID ережесі жетеді, байланыс жабық күйде сәтсіз болуы керек болса файрвол профилі жетеді, ал атаулар кеңістігі туннельді сырттағының бәрінен жасыратын жалғыз нұсқа.

Қатысты мақалалар