წარმოიდგინეთ Linux ჰოსტი, რომელიც ამთავრებს VPN-ს და ამავდროულად macvlan ქსელში კონტეინერს უშვებს. LAN არის 192.168.60.0/24, კონტეინერს აქვს 192.168.60.210, ხოლო VPN კლიენტები მოდიან 10.95.0.0/24-დან. კლიენტი აღწევს სერვისამდე, პასუხი არასოდეს ბრუნდება და ჰოსტზე ყოველი firewall წესი სწორად გამოიყურება. ამ სიმპტომს ორი ცალკე შეზღუდვა ქმნის და ერთის გასწორება მეორეს თავის ადგილზე ტოვებს.

ორი შეზღუდვა, ერთი სიმპტომი

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

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

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

ააგეთ ჰოსტის მხარის shim ვიწროდ

მეორე macvlan ინტერფეისი ჰოსტზე, რომელიც ხიდის რეჟიმში იმავე მშობელზეა მიბმული, ჰოსტის სტეკს საკუთარ იდენტობას აძლევს ამ LAN სეგმენტზე. გამოყავით მისთვის მისამართი DHCP აუზის გარეთ და კონტეინერის დიაპაზონის გარეთ და მხოლოდ კონტეინერი გაატარეთ მის გავლით.

ip link add macvlan-vpn link eth0 type macvlan mode bridge
ip address add 192.168.60.250/32 dev macvlan-vpn
ip link set macvlan-vpn up
ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250

პირველი ბრძანება ქმნის ინტერფეისს ხიდის რეჟიმში, რაც ამ დრაივერის დოკუმენტირებული ნაგულისხმევია და ის რეჟიმია, რომელიც გსურთ ჰოსტ-კონტეინერ ტრაფიკისთვის. მეორე ანიჭებს /32-ს, რათა მისამართი LAN პრეფიქსს არ დაეჯახოს, ხოლო მეოთხე shim-ის გავლით მხოლოდ კონტეინერის მისამართს აგზავნის.

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

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

გადაწყვიტეთ, როგორ შენარჩუნდება წყარო

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

ამის მუშაობისთვის კონტეინერის ქსელური კონფიგურაცია ამ გზისთვის 10.95.0.0/24-ის ტრაფიკი უნდა აგზავნიდეს 192.168.60.250-ზე, როგორც საკუთარ კარიბჭეზე. ეს არის თავად კონტეინერის კონფიგურაციაში არსებული მხარდაჭერილი მარშრუტის ან კარიბჭის პარამეტრი და არა ჰოსტის მხარის ხრიკი. დაადასტურეთ ის კონტეინერის შიგნიდან, ნაცვლად იმისა, რომ ჩათვალოთ პარამეტრის ძალაში შესვლა. ნაგულისხმევი კარიბჭე, რომელიც ჯერ კიდევ LAN როუტერზე მიუთითებს, პასუხებს იმავე ხვრელში აგზავნის.

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

iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250

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

შეამოწმეთ კლიენტიდან და არა ჰოსტიდან

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

curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210

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

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

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

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