მეორე OpenVPN კლიენტის დამატება ერთ Linux ჰოსტზე ორი ადგილიდან ერთ-ერთში ფეილდება. ან შიდა კლიენტი ვერ აღწევს საკუთარ სერვერამდე, რადგან გარე გვირაბმა ეს ტრანსპორტი დაიკავა, ან მეორე კლიენტი გადაწერს მარშრუტების ცხრილს და პირველი გვირაბი წყვეტს მუშაობას. ორივე პრობლემა მარშრუტიზაციაშია და არა დაშიფვრაში, და ორივე წყდება მანამ, სანამ ახალი გვირაბი რაიმე აპლიკაციურ ტრაფიკს გადაიტანს. აქ მოცემული მისამართები საილუსტრაციოა: tun0 არის გარე გვირაბი, 203.0.113.9 არის შიდა სერვერი, ხოლო TCP 9999 არის ნაკადი, რომელმაც შიდა გზა უნდა გამოიყენოს.

ორი წარუმატებლობის რეჟიმი, ერთი მარშრუტების ცხრილი

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

მეორე წარუმატებლობა სერვერის push-იდან მოდის. ჩვეულებრივი push არის redirect-gateway def1, რომელიც აყენებს 0.0.0.0/1 და 128.0.0.0/1-ს ნაგულისხმევი მარშრუტის შეცვლის ნაცვლად. ამიტომ ორი კლიენტი, რომელთაგან თითოეული საკუთარ /1 წყვილს აყენებს, ერთმანეთს ეჯახება, და უახლესი წყვილი იმარჯვებს თითქმის ყველა დანიშნულებისთვის. მოძებნეთ ეს ორი პრეფიქსი ცხრილში, როცა გვირაბი კვდება მეორის მიერთების შემდეგ, რადგან შესაძლოა თავად ნაგულისხმევი მარშრუტი არასდროს შეცვლილა.

მონიშნეთ ნაკადი და მიეცით ცხრილი

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

iptables -t mangle -A PREROUTING -p tcp -m multiport --dport 9999 -j MARK --set-mark 0x9999
ip rule add fwmark 0x9999 table 200 pref 1000
ip route add default dev tun1 table 200

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

წაართვით მარშრუტების საკუთრება მეორე კლიენტს

ორი ვარიანტი უშლის მეორე კლიენტს ცხრილის რედაქტირებას, და ისინი სხვადასხვა წერტილში მოქმედებენ. route-nopull უგულებელყოფს push-ით გამოგზავნილ მარშრუტის პარამეტრებს, ამიტომ არაფერი არ დგინდება. route-noexec იღებს push-ით გამოგზავნილ პარამეტრებს კლიენტის გარემოში, მაგრამ ცხრილის ცვლილებას hook-ს უტოვებს, და ეს არის ის, რაც გსურთ, როცა უნდა ნახოთ, რა შემოგვთავაზა სერვერმა.

Hook მუშაობს push-ით გამოგზავნილი მნიშვნელობებით თავის გარემოში, და მან მხოლოდ თქვენ მიერ დამტკიცებული ჩანაწერები უნდა დაამატოს. გახადეთ ის idempotent: გაასუფთავეთ მის საკუთრებაში არსებული ცხრილი ხელახლა აშენებამდე, და ნუ ჩათვლით, რომ წინა გაშვებამ სუფთა მდგომარეობა დატოვა. ხელახალი დაკავშირება კვლავ იძახებს hook-ს, და გასუფთავების გარეშე დამატებული hook აგროვებს დუბლირებულ მარშრუტებს.

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

დაამაგრეთ ორივე სერვერის მისამართი

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

ip route add 203.0.113.9/32 dev tun0
ip route get 203.0.113.9

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

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

გამოსცადეთ ჯაჭვი და გახადეთ წარუმატებლობა ხილული

გადაიღეთ გარე ინტერფეისზე, სანამ შიდა კლიენტი უკავშირდება. შიდა ხელის ჩამორთმევა უნდა გამოჩნდეს როგორც დაშიფრული ტვირთი გარე გვირაბის შიგნით; თუ ის ჩვეულებრივ UDP-დ გამოჩნდება 203.0.113.9-ისკენ, ჰოსტ-მარშრუტი აკლია და ჯაჭვი არასდროს აშენებულა.

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

დაასრულეთ ორი ნაკადით და წესების ერთი dump-ით: მონიშნული და აუნიშნავი კავშირები სხვადასხვა გზით უნდა წავიდეს, და ip rule show-მ უნდა ჩამოთვალოს ის პრიორიტეტი, რომელიც გქონდათ განზრახული. თუ ორივე ნაკადი ერთსა და იმავე გზას მიდის, ნიშანი არ გამოიყენება იქ, სადაც თქვენ ფიქრობთ.

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