RAND_bytes не успеа во OpenVPN: грешка во библиотеката или јазол што недостасува
Неуспехот на RAND_bytes може да значи одбиен извор на ентропија или јазол скриен од затвор. Прочитајте ја редицата грешки и приказот на процесот пред да создадете уреди.
RAND_bytes() failed е тврдење за еден локален примитив, не за сметката, претходно споделениот клуч или оддалечениот порт. Две многу различни грешки го создаваат истиот ред и оставаат различни траги. Едната е криптографски бекенд што одбива да испорача бајти; другата е процес што не го достигнува изворот на ентропија за кој е изграден неговиот код. Нивното разделување бара едно читање на редицата грешки и еден поглед на датотечниот систем на затворениот процес, а таа проверка припаѓа пред сето она што ќе се создаде под /dev.
Што разликува повратната вредност
Документираниот договор разликува три исходи, не два: 1 за успех, -1 кога вчитаниот метод RAND не го поддржува барањето, и 0 за другите грешки, при што објаснувањето останува во редицата грешки. Референцата за RAND_bytes додава точка што лесно се превидува: стандардниот генератор сее семе од оперативниот систем на поддржаните платформи, и кога тоа сеење не успее, тој останува во состојба на грешка наместо да врати предвидливи бајти.
Само еден од тие броеви го опишува опкружувањето. -1 е прашање на градба, добавувач или функција, бидејќи кодот побарал нешто што активната имплементација не го нуди. 0 со поплака за сеењето е прашање на опкружување, бидејќи генераторот воопшто не можел да добие ентропија. Бројот сам по себе никогаш не кажува кој, а ниту името на функцијата.
Кога скриениот јазол на уред е вистинската причина
Ограничената услуга гледа друго стебло од лушпата во која пишувате. Chroot затворите, сликите на контејнери и зацврстените unit-датотеки редовно прикажуваат /dev со помалку јазли од оној на домаќинот. Ако имплементацијата што не успева отвора /dev/urandom по патека, таа разлика е доволна да го скрши стартувањето додека самиот домаќин изгледа сосема здрав. Уред што постои надвор од затворот не докажува ништо за тоа што затворениот процес смее да го отвори.
Не секој случаен интерфејс има потреба од патека, сепак. Системскиот повик getrandom во Linux не прифаќа ни име на датотека ни датотечен дескриптор, а неговата страница од прирачникот забележува дека тоа својство е корисно токму таму каде chroot крие патеки на уреди.
Значи, објаснувањето за јазолот што недостасува е хипотеза за една гранка од кодот, не правило за случајните броеви воопшто. Држи кога доказите именуваат патека, и е нагаѓање кога доказите именуваат нешто друго.
Прво прочитајте ја редицата грешки, потоа приказот на процесот
Најбрзиот начин да го решите прашањето е да прочитате што библиотеката веќе забележала, а потоа директно да го погледнете приказот внатре во затворот. Започнете со градбата на 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
Изведувајте ги тие читања врз истиот процес, не врз лушпата што случајно е отворена. Споредувањето на /dev на домаќинот со приказот на неповрзан процес е начинот на кој погрешната зависност се поправа двапати.
Додајте ја зависноста само кога можете да ја именувате
Кога доказите навистина именуваат патека, поправката е мала: направете ја таа единствена патека достапна внатре во затворот и оставете сето друго на мира. Bind mount на поединечниот јазол обично е доволен, а mknod со стандардните major и minor броеви на јазолот дава ист резултат во инсталации каде mount не е опција. Проширувањето на песочникот, давањето пристап до секој знаковен уред или исклучувањето на PrivateDevices ја менува насочената исправка за трајна безбедносна регресија.
Ентрописки демон не е замена за таа поправка. Пакетите како haveged менуваат како се храни језгрениот базен; тие не можат да создадат патека што затворениот процес смее да ја отвори. Инсталирањето на еден може да го подобри графикот за здравје додека повикот open сѐ уште не успева. Држете ги двата проблема одвоени, инаку следниот неуспех повторно ќе му се припише на погрешниот слој.
Проверете ги генераторот и тунелот одделно
Престартувањето е единствениот тест што повторно ја користи истата конфигурација, истата unit-датотека и истата изолација што го предизвикале неуспехот. Изведете го, а потоа читајте ги најновите записи во дневникот наместо примерок од претходно стартување.
sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'
Во тој излез барајте две одделени работи: пораката за случајниот извор што исчезнува и тунелот што ја достигнува својата вообичаена стартна пресвртница. Генератор што повторно работи отстранува еден локален неуспех и не кажува ништо за идентитетот на серверот, акредитивите или рутирањето. Тестирајте го тоа со истата клиентска конфигурација што претходно не успеа, за резултатот да биде споредлив, а не само подобар.