RAND_bytes OpenVPN-ში ვერ მუშაობს: ბიბლიოთეკის შეცდომა ან დაკარგული კვანძი
RAND_bytes-ის წარუმატებლობა შეიძლება ნიშნავდეს უარყოფილ entropia-ს წყაროს ან jail-ით დამალულ კვანძს. წაიკითხეთ შეცდომების რიგი და პროცესის ხედი, სანამ მოწყობილობებს შექმნით.
RAND_bytes() failed არის განცხადება ერთი ლოკალური პრიმიტივის შესახებ და არა ანგარიშის, წინასწარ გაზიარებული გასაღების ან დისტანციური პორტის შესახებ. ორი ძალიან განსხვავებული ხარვეზი ერთსა და იმავე ხაზს ქმნის და სხვადასხვა კვალს ტოვებს. ერთი კრიპტოგრაფიული backend-ია, რომელიც ბაიტების გაცემაზე უარს ამბობს; მეორე პროცესია, რომელიც ვერ აღწევს იმ entropia-ს წყაროს, რომლისთვისაც მისი კოდი აშენდა. მათი გამიჯვნა მოითხოვს შეცდომების რიგის ერთ წაკითხვას და გამოკეტილი პროცესის ფაილური სისტემის ხედზე ერთ შეხედვას, და ეს შემოწმება უნდა მოხდეს /dev-ის ქვეშ რაიმეს შექმნამდე.
რას განასხვავებს დაბრუნების მნიშვნელობა
დოკუმენტირებული ხელშეკრულება განასხვავებს სამ შედეგს და არა ორს: 1 წარმატებისთვის, -1 როცა ჩატვირთული RAND მეთოდი მოთხოვნას არ უჭერს მხარს, და 0 სხვა ხარვეზებისთვის, განმარტება კი შეცდომების რიგში რჩება. RAND_bytes-ის ცნობარი ამატებს პუნქტს, რომლის გამოტოვებაც ადვილია: ნაგულისხმევი გენერატორი მხარდაჭერილ პლატფორმებზე ოპერაციული სისტემიდან იღებს თესლს და როცა ეს დათესვა ვერ ხდება, ის ხარვეზის მდგომარეობაში რჩება, ნაცვლად იმისა რომ წინასწარმეტყველადი ბაიტები დააბრუნოს.
მხოლოდ ერთი ამ რიცხვებიდან აღწერს გარემოს. -1 არის აწყობის, მომწოდებლის ან ფუნქციის საკითხი, რადგან კოდმა მოითხოვა ის, რასაც აქტიური იმპლემენტაცია არ გვთავაზობს. 0 დათესვის ჩივილით გარემოს საკითხია, რადგან გენერატორმა entropia საერთოდ ვერ მიიღო. რიცხვი თავისთავად არასდროს ამბობს რომელი, და ფუნქციის სახელიც არ ამბობს.
როცა დამალული მოწყობილობის კვანძი ნამდვილი მიზეზია
შეზღუდული სერვისი სხვა ხეს ხედავს, ვიდრე shell-ს, რომელშიც წერთ. Chroot jail-ები, კონტეინერის იმიჯები და გამაგრებული unit ფაილები ჩვეულებრივ გვთავაზობენ /dev-ს, რომელიც ჰოსტისაზე ნაკლებ კვანძს შეიცავს. თუ წარუმატებელი იმპლემენტაცია /dev/urandom-ს გზის სახელით ხსნის, ეს განსხვავება საკმარისია გაშვების დასაშლელად, მაშინ როცა თავად ჰოსტი სრულიად ჯანმრთელად გამოიყურება. Jail-ის გარეთ არსებული მოწყობილობა არაფერს ამტკიცებს იმის შესახებ, თუ რისი გახსნა შეუძლია გამოკეტილ პროცესს.
თუმცა ყველა შემთხვევით ინტერფეისს გზა არ სჭირდება. Linux-ის getrandom სისტემური გამოძახება არ იღებს არც ფაილის სახელს და არც ფაილის დესკრიპტორს, და მისი სახელმძღვანელოს გვერდი აღნიშნავს, რომ ეს თვისება სწორედ იქ არის სასარგებლო, სადაც chroot მოწყობილობის გზებს მალავს.
ამიტომ დაკარგული კვანძის ახსნა კოდის ერთი ტოტის შესახებ ჰიპოთეზაა და არა ზოგადი წესი შემთხვევითი რიცხვების შესახებ. ის ძალაშია, როცა მტკიცებულება გზას ასახელებს, და ვარაუდია, როცა მტკიცებულება სხვა რამეს ასახელებს.
ჯერ შეცდომების რიგი წაიკითხეთ, შემდეგ პროცესის ხედი
კითხვის გადაწყვეტის ყველაზე სწრაფი გზა ის არის, რომ წაიკითხოთ, რაც ბიბლიოთეკამ უკვე ჩაწერა, და შემდეგ უშუალოდ შეხედოთ jail-ის შიგნით არსებულ ხედს. დაიწყეთ იმ OpenSSL-ის აწყობით, რომელიც სერვისმა რეალურად ჩატვირთა, რადგან მომწოდებლის დასტები განსხვავდება ძირითად ვერსიებსა და დისტრიბუციებს შორის. შემდეგ ჰკითხეთ systemd-ს, რომელი პროცესი მუშაობს და რა შეზღუდვები ვრცელდება მასზე. მხოლოდ მას შემდეგ, რაც ორივე ფაქტი მაგიდაზეა, ღირს იმ კვანძების ჩამოთვლა, რომელთა ნახვაც ამ პროცესს შეუძლია.
openssl version -a
systemctl show openvpn-server@lab -p MainPID -p PrivateDevices -p DevicePolicy
pid=$(systemctl show -p MainPID --value openvpn-server@lab)
sudo ls -l /proc/"$pid"/root/dev/urandom /proc/"$pid"/root/dev/random
ეს წაკითხვები იმავე პროცესზე შეასრულეთ და არა იმ shell-ზე, რომელიც შემთხვევით ღიაა. ჰოსტის /dev-ის შედარება უკავშირო პროცესის ხედთან არის ის გზა, რომლითაც არასწორი დამოკიდებულება ორჯერ სწორდება.
დამოკიდებულება მხოლოდ მაშინ დაამატეთ, როცა მისი დასახელება შეგიძლიათ
როცა მტკიცებულება ნამდვილად ასახელებს გზას, შესწორება მცირეა: ის ერთი გზა jail-ის შიგნით ხელმისაწვდომი გახადეთ და დანარჩენი ყველაფერი მშვიდად დატოვეთ. ერთი კვანძის bind mount ჩვეულებრივ საკმარისია, და mknod კვანძის სტანდარტული major და minor ნომრებით იმავე შედეგს იძლევა იმ ინსტალაციებზე, სადაც mount პარამეტრი არ არის. Sandbox-ის გაფართოება, ყველა სიმბოლო მოწყობილობაზე წვდომის მიცემა ან PrivateDevices-ის გამორთვა მიზანმიმართულ შესწორებას მუდმივი უსაფრთხოების რეგრესიით ცვლის.
Entropia-ს დემონი ამ შესწორების შემცვლელი არ არის. haveged-ის მსგავსი პაკეტები ცვლიან, როგორ იკვებება ბირთვის აუზი; მათ არ შეუძლიათ შექმნან გზის სახელი, რომლის გახსნაც გამოკეტილ პროცესს შეუძლია. ერთის დაყენებამ შეიძლება ჯანმრთელობის გრაფიკი უკეთესად აჩვენოს, მაშინ როცა გახსნის გამოძახება კვლავ ვერ ხერხდება. ორი პრობლემა ცალკე შეინახეთ, თორემ შემდეგი ხარვეზი ისევ არასწორ ფენას მიეკუთვნება.
გენერატორი და გვირაბი ცალ-ცალკე შეამოწმეთ
გადატვირთვა ერთადერთი ტესტია, რომელიც იმავე კონფიგურაციას, იმავე unit ფაილს და იმავე იზოლაციას იყენებს, რამაც ხარვეზი გამოიწვია. გაუშვით ის და შემდეგ წაიკითხეთ ჟურნალის უახლესი ჩანაწერები და არა ადრინდელი გაშვების ნიმუში.
sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'
ამ გამოსავალში ორი ცალკეული რამ მოძებნეთ: შემთხვევითი წყაროს შესახებ შეტყობინების გაქრობა და გვირაბის თავის ჩვეულ გაშვების ეტაპამდე მისვლა. გენერატორი, რომელიც ისევ მუშაობს, ერთ ლოკალურ ხარვეზს აცილებს და არაფერს ამბობს სერვერის იდენტობაზე, სერთიფიკატებზე ან მარშრუტიზაციაზე. გამოსცადეთ ეს იმავე კლიენტის კონფიგურაციით, რომელიც ადრე ვერ მუშაობდა, რომ შედეგი შედარებადი იყოს და არა უბრალოდ უკეთესი.