კონტეინერი, რომელიც ვერ აღწევს ვერაფერს კორპორატიული VPN-ის მიღმა, ჩვეულებრივ ცხოვრობს გვირაბისგან განსხვავებულ ქსელურ სახელთა სივრცეში. ჰოსტის კლიენტის მარშრუტები, DNS სერვერები და ფაირვოლის ნიშნები ჰოსტის სტეკს ეკუთვნის; ხიდის ქსელის კონტეინერს საკუთარი აქვს. ეს ერთი ფაქტი ხსნის პლატფორმის გუნდამდე მისულ რეპორტების უმეტესობას და ესვეა მიზეზი, რატომაც «VPN გატეხილია» და «Docker გვივლის VPN-ს» შეიძლება ერთდროულად მცდარი იყოს. ერთი სიმპტომის მიღმა ორი სრულიად განსხვავებული კონფიგურაცია იმალება, ამიტომ სანამ რომელიმე პარამეტრს შეცვლით, დაადგინეთ რომელი გაქვთ.

გაარკვიეთ, ვის სახელთა სივრცეს ეკუთვნის გვირაბი

macOS-ისა და Windows-ის Docker Desktop-ზე კონტეინერები Linux ვირტუალურ მანქანაში მუშაობს. სამუშაო მაგიდაზე დაყენებული VPN კლიენტი გვირაბს სამუშაო მაგიდის ოპერაციულ სისტემაში ქმნის და ვირტუალური მანქანა მას ვერასოდეს ხედავს. არცერთი კონტეინერის კონფიგურაცია ამას არ ასწორებს, რადგან ის ინტერფეისი, რომელიც კონტეინერს დასჭირდებოდა, მის ქსელურ სახელთა სივრცეში საერთოდ არ არსებობს.

Linux ჰოსტზე გვირაბი ჰოსტის სახელთა სივრცეში ცხოვრობს და ხიდის კონტეინერები ჩვეულებრივ ჰოსტის მარშრუტიზაციის ცხრილის მეშვეობით აღწევენ მას, გასვლისას წყაროს NAT-ის გამოყენებით. როცა ეს გზა ფუჭდება, მიზეზი ჩვეულებრივ გადაცემის პოლიტიკა, საპირისპირო გზის ფილტრაცია ან გადაფარებული ქვექსელი და არა დაკარგული მარშრუტი. სანამ გააგრძელებთ კითხვას, დაადასტურეთ ორი სამყაროდან რომელში ხართ:

docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5

ამ ორ მარშრუტიზაციის ცხრილს შორის სხვაობა მთელი პრობლემაა ერთ ეკრანზე. თუ ჰოსტის ხედი შეიცავს გვირაბის ინტერფეისს, ხიდის ხედი კი არა, თქვენ ხედავთ სახელთა სივრცეების იზოლაციას და დანარჩენი ყველაფერი არჩევანია, როგორ გადაკვეთოთ ის.

ჰოსტის ქსელი გამოცდაა და არა დიზაინი

კონტეინერის ჰოსტის ქსელით გაშვება, რასაც Docker ჰოსტის ქსელური სახელთა სივრცის გაზიარებად აღწერს, აიძულებს მას პირდაპირ მემკვიდრეობით მიიღოს გვირაბის ინტერფეისი და მისი მარშრუტები. თუ იგივე მოთხოვნა შემდეგ წარმატებით სრულდება, მარშრუტების თეორია დადასტურებულია და ხარვეზი სახელთა სივრცეების იზოლაციაა და არა სერთიფიკატები, DNS ან წვდომის წესი.

docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health

შეინახეთ ის დიაგნოსტიკად. ჰოსტის ქსელი უარს ამბობს პორტების გამოქვეყნებაზე და იმ იზოლაციის უმეტეს ნაწილზე, რომელიც კონტეინერისგან გსურდათ, ხოლო Docker Desktop-ზე «host» ნიშნავს ვირტუალურ მანქანას და არა სამუშაო მაგიდას, ამიტომ იქ წარმატებამ ან მარცხმა შეიძლება შეგიყვანოს შეცდომაში, თუ დაგავიწყდათ რომელ ჰოსტს მიმართავდით.

tun მოწყობილობა და მასთან მოსული უფლებები

კონტეინერის შიგნით VPN კლიენტს სჭირდება გვირაბის მოწყობილობა და მისი კონფიგურაციის ნებართვა. ჩვეულებრივი მოკლე გზაა --privileged, რომელიც ყველა მოწყობილობას აძლევს და ასუსტებს უსაფრთხოების პოლიტიკას მთელ კონტეინერში. ეს გაცილებით მეტია, ვიდრე ამ სამუშაოს სჭირდება და ძნელია გამართლება განხილვისას.

sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client

უფრო ვიწრო ფორმა ერთ მოწყობილობის კვანძს ასახავს და მხოლოდ ქსელის ადმინისტრირების უნარს ამატებს. ჯერ ჰოსტზე ჩატვირთეთ მოდული, რომ კვანძი არსებობდეს. თუ კონტეინერი ირთვება და კლიენტი იტყობინება, რომ გვირაბის მოწყობილობას ვერ ხსნის, შეამოწმეთ ასახვა სანამ პროფილს დააეჭვებთ, რადგან ეს შეცდომა ჩვეულებრივ პირდაპირი მნიშვნელობითაა.

ეს დიზაინი ასევე ნიშნავს, რომ კლიენტი თითო კონტეინერზე მუშაობს. ეს სწორი პასუხია, როცა თითოეულ დატვირთვას საკუთარი გვირაბი სჭირდება, და არასწორი, როცა უბრალოდ გინდოდათ ჰოსტის გვირაბი თვალსაჩინო ყოფილიყო, რასაც პლატფორმის გუნდი ალბათ ვარაუდობდა.

ხიდის NAT ცვლის წყაროს, რომელსაც VPN ხედავს

ნაგულისხმევი ხიდის შემთხვევაში კონტეინერის გამავალი ტრაფიკი ჰოსტის მისამართზე ითარგმნება. ამიტომ VPN-ის მიღმა კორპორატიული მხარე ხედავს ჰოსტის გვირაბის მისამართს და არა კონტეინერისას, წყაროზე დაფუძნებული წვდომის წესები ისე იქცევა, თითქოს მოთხოვნა ჰოსტმა გაგზავნა, და ორი კონტეინერი VPN სერვერისთვის განურჩეველი ხდება.

macvlan ან ipvlan სამაგიეროდ კონტეინერს LAN-ის მისამართს აძლევს, რაც LAN-ში აღმოჩენას ეხმარება და კონტეინერს სეგმენტზე თანასწორად აჩვენებს. ის ასევე მთლიანად გვერდს უვლის ჰოსტის გვირაბს, ამიტომ ასეთი კონტეინერი ვერ მიაღწევს მხოლოდ-VPN პრეფიქსებს, თუ VPN იმავე LAN-იდანაც არ არის ხელმისაწვდომი.

ორივე ფორმა ლეგიტიმურია; ისინი სხვადასხვა მოთხოვნას პასუხობენ. თუ მოთხოვნაა «ეს კონტეინერი უნდა აღწევდეს მხოლოდ-VPN სერვისამდე», თქვენ ირჩევთ ჰოსტის გავლით მარშრუტიზაციასა და კონტეინერში გვირაბის დასრულებას შორის. ეს არჩევანი ჩაწერეთ განლაგებამდე და არა პირველი წარუმატებელი მოთხოვნის შემდეგ. რასაც არ უნდა აირჩიოთ, ჩაწერეთ წყაროს მისამართი, რომელსაც შორეული მხარე დაინახავს, რადგან ზუსტად ამას აჩვენებს მისი წვდომის წესები და ჟურნალები. დიზაინი, რომელიც ვერ ასახელებს ამ მისამართს, დაუმთავრებელია.

DNS მიჰყვება დემონს და არა გვირაბს

კონტეინერი თავისი გადამწყვეტის კონფიგურაციას გაშვებისას იღებს, დემონიდან ან იმიჯიდან კოპირებულს. მისამართები, რომლებსაც VPN დაკავშირების შემდეგ უგზავნის, ძალიან გვიან ჩამოდის ამ ასლისთვის და ისინი ჰოსტის გადამწყვეტში იგზავნება და არა კონტეინერში.

დააყენეთ გადამწყვეტი სერვისისთვის ცალსახად, ან მიუთითეთ შიდა გადამწყვეტზე, რომელიც გვირაბის მეშვეობით ხელმისაწვდომია. კონტეინერი, რომელიც პირად სახელს საჯარო მისამართად წყვეტს, ჩვეულებრივ საჯარო გადამწყვეტს იყენებს და არ იტანჯება გატეხილი მარშრუტით, ხოლო შესწორება compose ფაილს ან დემონის კონფიგურაციას ეკუთვნის.

იგივე მსჯელობა ეხება გასვლის მისამართის საკითხს. თუ თითოეული კონტეინერი სხვადასხვა VPN მისამართიდან უნდა ჩანდეს, ერთი ჰოსტის გვირაბი ამას ვერ უზრუნველყოფს, რადგან NAT ისინი ერთ წყაროდ აჭერს. სამუშაო ფორმებია კლიენტი თითოეული კონტეინერის სახელთა სივრცეში ან sidecar, რომელიც ფლობს გვირაბს და თავის სტეკს იზიარებს, და ორივე ცვლის, როგორ მიემართება აპლიკაცია.

ჩამონათვალი ბილეთის დახურვამდე: დაადგინეთ გვირაბის მფლობელი სახელთა სივრცე, დაამტკიცეთ გზა ჰოსტის ქსელით, ასახეთ მხოლოდ საჭირო tun მოწყობილობა, დაიმახსოვრეთ წყაროს მისამართი NAT-ის შემდეგ, დააყენეთ გადამწყვეტი ცალსახად და თითო კონტეინერის გასვლის მისამართებს მოეპყარით როგორც არქიტექტურულ გადაწყვეტილებას და არა დროშას.

დაკავშირებული სტატიები