რატომ აჩვენებს თქვენი iOS VPN აპი გათიშულს, როცა გვირაბი მუშაობს
თქვენი iOS აპი გვირაბს მართავს, მაგრამ არ ფლობს მას, და მენეჯერის მდგომარეობა ქეშირებულია. ჯერ პარამეტრები ჩატვირთეთ, შემდეგ წაიკითხეთ სტატუსი და ინტერფეისის მრიცხველები.
თქვენი აპი ამბობს გათიშულს, მენიუს ზოლი ამბობს დაკავშირებულს, და ტრაფიკი აშკარად მიედინება. ეს უფსკრული არ არის სარბენი მდგომარეობა, რომელსაც ხელახალი ცდით გამოასწორებთ: აპი და გვირაბი ცალკე პროცესებია, და ობიექტი, რომელსაც თქვენი კოდი კითხულობს, სისტემის მიერ შენახული კონფიგურაციის ქეშირებული ხედია. Apple-ის Personal VPN ზედაპირი მართვის API-ია, არა მონაცემთა გზა, და მისი უცნაური ქცევის უმეტესობა სწორედ ამ ერთი ფაქტიდან გამომდინარეობს. აი, რა ხდება სინამდვილეში თითოეულ გამოძახებაზე.
მენეჯერის ობიექტი ქეშირებული ხედია, არა გვირაბი
NETunnelProviderManager ივსება სისტემის საკუთრებაში არსებული პარამეტრების საცავიდან, ამიტომ მისი თვისებები არაფერს ნიშნავს, სანამ loadFromPreferences არ დასრულდება. თუ ამის წინ წაიკითხავთ connection.status-ს, მიიღებთ ნაგულისხმევ მნიშვნელობას, და სწორედ ამიტომ აცხადებს გადატვირთვის შემდეგ პირველი სტატუსის განახლება გათიშულს, როცა გვირაბი მუშაობს. ჯერ ჩატვირთეთ, შემდეგ წაიკითხეთ სტატუსი და პროტოკოლის კონფიგურაცია იმავე დასრულების დამმუშავებლიდან. შემდგომი ცვლილებები დააკვირდით NEVPNStatusDidChange-ის მეშვეობით, პერიოდული შეკითხვების ნაცვლად, და გაითვალისწინეთ, რომ შეტყობინება ირთვება On Demand-ით დაწყებული კავშირებისთვისაც, სადაც საერთოდ არ არსებობს აპის გამოძახება, რომ რამე დააბრუნოს. იგივე ეხება პროტოკოლის პარამეტრებს: ისინი იკითხება ჩატვირთული კონფიგურაციიდან, და არა იმისგან, რაც აპმა გადასცა.
თავად გვირაბი ცხოვრობს Network Extension პროვაიდერის პროცესში, ამიტომ აპმა შეიძლება დაკარგოს საკუთარი მდგომარეობა კავშირის დაკარგვის გარეშე. ყველაფერი, რასაც ინტერფეისი აჩვენებს, მენეჯერიდან უნდა აღდგეს, და არა გასული სესიიდან გაიხსენოს.
გაშვების თანმიმდევრობა: შეინახე, ჩატვირთე, შემდეგ გაუშვი
პროვაიდერზე დაფუძნებულ კავშირს სამი ნაბიჯი სჭირდება თანმიმდევრობით. ჩაწერეთ პროვაიდერის კონფიგურაცია და გამოიძახეთ saveToPreferences, ჩატვირთეთ მენეჯერი, რომ შენახული კონფიგურაცია იყოს ის, რაც ხელში გაქვთ, შემდეგ გაუშვით NETunnelProviderSession.startVPNTunnel()-ის მეშვეობით. თუ შენახვას გამოტოვებთ, გაშვებას არაფერი აქვს გასაშვები; თუ შენახვამდე ჩატვირთავთ, მენეჯერი კვლავ ძველ კონფიგურაციას ასახავს.
startVPNTunnel-ის მიერ დაბრუნებული ლოგიკური მნიშვნელობა მხოლოდ ამბობს, რომ მოთხოვნა მიღებულია. პროვაიდერის დონის წარუმატებლობები მოგვიანებით მოდის, როგორც სტატუსის ცვლილება გათიშულზე, რასაც NEVPNStatusDidChange შეტყობინებით აკვირდებით, და შეტყობინების დამმუშავებელმა loadFromPreferences-ის შემდეგ ხელახლა უნდა წაიკითხოს connection.status, რადგან ქეშირებული მნიშვნელობა შეიძლება ჯერ კიდევ ძველი იყოს. მოთხოვნის დონის წარუმატებლობები მაშინვე ბრუნდება გამონაკლისის მსროლელი ფორმიდან ან startVPNTunnelAndReturnError:-ის შეცდომის გამომავალი პარამეტრიდან. კოდი, რომელიც დაბრუნებულ მნიშვნელობას შედეგად თვლის, აცხადებს კავშირზე, რომელიც არასდროს დამყარდა. სხვა ჩუმი მარცხი პროვაიდერის პაკეტის იდენტიფიკატორია, რომელიც არ ემთხვევა დაყენებულ გაფართოებას: მოთხოვნა უარყოფილია, და შეტყობინებაში არაფერი მიუთითებს იდენტიფიკატორზე. თუ იდენტიფიკატორი არასწორია, მოთხოვნა ჩვეულებრივ მაშინვე ვარდება, სანამ პროვაიდერის რომელიმე ჟურნალის სტრიქონი გამოჩნდება.
გაშვების შემდეგ პარამეტრების ხელახალი ჩატვირთვაა ის, რაც სტატუსის ეკრანებს სწორებს. მენეჯერი არ გიბიძგებთ ახალ კონფიგურაციას, როცა სისტემა ცვლის მას.
ნდობის მასალა პროფილით მოდის, არასდროს აპის კოდიდან
აპს არ აქვს მხარდაჭერილი გზა ფესვური სერტიფიკატის iOS-ის ნდობის საცავში დასამატებლად, ამიტომ Personal VPN კონფიგურაციას შეუძლია მხოლოდ იმ მასალაზე მიუთითოს, რომელსაც მოწყობილობა უკვე ენდობა: დაყენებული პროფილის, მოწყობილობის მართვის ან სისტემის მიერ სხვა მიზეზებით სანდო CA-ს მიერ დამყარებულ ჯაჭვზე. აპი, რომელიც პირველ გაშვებაზე საკუთარ CA-ს ქმნის და ელის, რომ სისტემა მას აღიარებს, პროვაიდერის შიგნით ვალიდაციაზე ჩავარდება, სადაც აპის ინტერფეისი მიზეზს ვერ ხედავს.
მოეპყარით ამ საზღვარს, როგორც დიზაინის იმ შეზღუდვას, რომელიც არის, და ნდობის ღუზა რეგისტრაციის პროფილთან ერთად მიაწოდეთ. VPN-ის აუთენტიფიკაცია ნდობის გადაწყვეტილებისგან ცალკე შეინახეთ, რადგან ისინი სხვადასხვა ადგილას ვარდება და სხვადასხვა ადამიანი ახდენს მათ დებაგირებას.
მრიცხველები ინტერფეისიდან მოდის, არა VPN API-დან
მენეჯერი ამჟღავნებს სტატუსს და კონფიგურაციას, და არაფერს, რაც გვირაბზე ბაიტებს ითვლის. თუ გამოყენების რიცხვები გჭირდებათ, გამოიძახეთ getifaddrs() და წაიკითხეთ if_data შესაბამისი ინტერფეისისთვის: en0 Wi-Fi-სთვის, pdp_ip ინტერფეისები მობილურისთვის, და utun მოწყობილობა თავად გვირაბისთვის. utun-ის მრიცხველები შიდა ტრაფიკს აღწერს და მოიცავს პროტოკოლის ზედნადებს.
ეს რიცხვები შეფასებებია, არა აპების მიხედვით აღრიცხვა, და ისინი ნულდება, როცა ინტერფეისი ხელახლა იქმნება. ინტერფეისში ასე მონიშნეთ, თორემ ვიღაც მათ კლიენტისთვის ინვოისის გასაწერად გამოიყენებს. თუ აპების მიხედვით რიცხვები გჭირდებათ, სრულიად სხვა მექანიზმი გჭირდებათ, და არა ამ ველების უკეთესი წაკითხვა.
გასუფთავება stopVPNTunnel-ს ეკუთვნის, არა დასრულებას
applicationWillTerminate გაძლევთ რამდენიმე წამს, სანამ სისტემამ შეიძლება პროცესი მოკლას, რაც საიმედო ადგილი არ არის კავშირის დასაშლელად. გაგზავნეთ გაჩერება stopVPNTunnel()-ზე ან დაამუშავეთ ის პროვაიდერის გაჩერების უკუგამოძახებაში, და შეინახეთ მენეჯერის ან კონფიგურაციის იდენტიფიკატორი, რომლითაც დაიწყეთ, რათა გაჩერებამ სწორედ ის კავშირი დაამიზნოს და არა მოწყობილობის ყველა კონფიგურაცია.
შეინახეთ ეს იდენტიფიკატორი იმ პროფილის გვერდით, რომელსაც ეკუთვნის, რადგან მენეჯერის ობიექტი არ აღრიცხავს, რომელი კონფიგურაცია აირჩია მომხმარებელმა. და გახსოვდეთ, რომ On Demand-ის მიერ აწეულ კავშირს უკან საერთოდ არ აქვს აპის გამოძახება, ამიტომ სტატუსის ეკრანმა მაინც უნდა ჩატვირთოს პარამეტრები, სანამ რამეს დახატავს.