როგორ გავატაროთ ერთი აპლიკაცია VPN-ით მთელი მანქანის გარეშე
არც ერთი არამართული დესკტოპი არ გვთავაზობს VPN-ის გადამრთველს თითოეული პროცესისთვის. აირჩიეთ ის შრე, რომელიც ირჩევს ტრაფიკს: მიბმული სოკეტი, UID წესი, ფაირვოლის პროფილი ან SOCKS ნახტომი.
VPN კლიენტი უკავშირდება, ბრაუზერი მუშაობს, და ის ერთი ბრძანება, რომელიც ნამდვილად გაინტერესებთ, მაინც სახლის კავშირით გადის. ან პირიქით ხდება: გვირაბი იკავებს ნაგულისხმევ მარშრუტს და ლოკალური ფაილური სერვერი დესკტოპიდან ქრება. ეს შემხვდა აწყობის აგენტთან, რომელსაც შიდა არტეფაქტების სარკემდე უნდა მიეღწია, სანამ ჰოსტის დარჩენილი ნაწილი ოფისის LAN-ზე რჩებოდა, და კლიენტმა ზუსტად ორი არჩევანი შესთავაზა: მთელი ტრაფიკი ან არაფერი. მოთხოვნა ორივე მიმართულებით ერთია, ეს პროგრამა და არა მთელი მანქანა, და კლიენტების უმეტესობას ამისთვის არც ჩამრთველი უჯრა აქვს, რადგან მარშრუტების ცხრილმა არასოდეს იცოდა რა არის პროგრამა.
რატომ ვერ ხედავს მარშრუტების ცხრილი თქვენს პროგრამას
როცა პროცესი პაკეტს აგზავნის, სტეკი დანიშნულების მისამართს მარშრუტების ცხრილში ეძებს. არც შესრულებადი ფაილის სახელი და არც პორტი ამ ძიებაში არ შედის. დომენური სახელები იმავე მიზეზით ვარდება: გვირაბი ტრაფიკს მისამართამდე მიჰყავს, და როცა სახელი მისამართად ითარგმნება, მარშრუტიზაცია ერთადერთი ბერკეტია, რაც ბირთვს ჯერ კიდევ დარჩა. ამიტომ „VPN მხოლოდ ამ საიტისთვის“ საბოლოოდ პროქსის ნიშნავს, და „VPN მხოლოდ ამ პროგრამისთვის“ მექანიზმების მცირე ნაკრებიდან ერთს.
| Mechanism | What selects | Covers | On tunnel drop |
|---|---|---|---|
| Socket bind | source address | a client you control | connections fail |
| UID rule (Linux) | owning user | every process of one account | connections fail |
| Firewall profile (Windows) | adapter profile | one program | fails closed |
| Network namespace | namespace membership | everything started inside | connections fail |
| SOCKS hop | app proxy setting | one app or one browser profile | connections 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, და source_address არგუმენტი Python-ის HTTP კლიენტებში. მისამართი გვირაბს უნდა ეკუთვნოდეს, და აქ დაშვებული შეცდომა ჩვეულებრივი კავშირის შეცდომად ვარდება, არა მარშრუტიზაციის ჩივილად. მისამართის ნაცვლად მოწყობილობის სახელზე მიბმა 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 პროქსიმ უნდა გადაწყვიტოს (socks5h curl-ში), თორემ სახელი ლოკალურ გადამწყვეტში გაჟონავს.
შეინახეთ მსმენელი ადგილობრივ მარყუჟზე, თუ სხვა მანქანას არ სჭირდება.
გზა შეამოწმეთ დაჭერით და არა სტატუსის შეტყობინებით
აპლიკაციის სტატუსის ფანჯრები პარამეტრს აღწერენ და არა პაკეტს. დაიჭირეთ ორივე ინტერფეისზე და შეადარეთ:
tcpdump -i any -n port 443
ss -tnp | grep 443თუ კავშირი ფიზიკურ ინტერფეისზე ჩნდება გვირაბზე შესაბამისი ჩანაწერის გარეშე, ამრჩევი არ მოქმედებს, რასაც არ უნდა იტყობინებოდეს კლიენტი. ცალკე შეამოწმეთ IPv6 და გადამწყვეტი, და შეამოწმეთ მეორე გზა, მაგალითად დამხმარე პროცესი ან მემკვიდრეობით მიღებული სისტემური პროქსი.
შემდეგ აირჩიეთ საზღვარი, რომელიც მოთხოვნას შეესაბამება: პროქსი საკმარისია ერთი საიტისთვის, UID წესი საკმარისია ერთი ანგარიშისთვის, ფაირვოლის პროფილი საკმარისია, როცა კავშირი დახურულად უნდა ვარდებოდეს, და სახელების სივრცე ერთადერთი ვარიანტია, რომელიც გვირაბს მის გარეთ ყველაფრისგან მალავს.