RAND_bytes-ը OpenVPN-ում ձախողվել է՝ գրադարանի սխալ կամ բացակայող հանգույց
RAND_bytes-ի ձախողումը կարող է նշանակել մերժված էնտրոպիայի աղբյուր կամ jail-ով թաքցված հանգույց։ Կարդացեք սխալների հերթը և գործընթացի տեսքը՝ նախքան սարքեր ստեղծելը։
RAND_bytes() failed-ը հայտարարություն է մեկ լոկալ պրիմիտիվի մասին, ոչ թե հաշվի, նախապես բաշխված բանալու կամ հեռավոր պորտի։ Երկու շատ տարբեր խափանումներ առաջացնում են նույն տողը և թողնում տարբեր հետքեր։ Մեկը կրիպտոգրաֆիկ backend է, որը հրաժարվում է բայթեր թողարկել՝ մյուսը գործընթաց է, որը չի հասնում այն էնտրոպիայի աղբյուրին, որի համար կառուցվել է նրա կոդը։ Դրանք տարանջատելու համար պետք է մեկ ընթերցում սխալների հերթից և մեկ հայացք բանտարկված գործընթացի ֆայլային համակարգի տեսքին, և այդ ստուգումը պետք է նախորդի այն ամենին, ինչ ստեղծվում է /dev-ի տակ։
Ինչ է տարբերակում վերադարձվող արժեքը
Փաստաթղթավորված պայմանագիրը տարբերակում է երեք ելք, ոչ թե երկու՝ 1 հաջողության դեպքում, -1 երբ բեռնված RAND մեթոդը չի աջակցում հարցմանը, և 0 այլ խափանումների դեպքում, ընդ որում բացատրությունը մնում է սխալների հերթում։ RAND_bytes-ի հղումը ավելացնում է մի կետ, որը հեշտ է բաց թողնել՝ լռելյայն գեներատորը սերմը վերցնում է օպերացիոն համակարգից աջակցվող պլատֆորմներում, և երբ այդ սերմավորումը ձախողվում է, այն մնում է սխալի վիճակում՝ կանխատեսելի բայթեր վերադարձնելու փոխարեն։
Այդ թվերից միայն մեկն է նկարագրում միջավայրը։ -1-ը կառուցման, մատակարարի կամ ֆունկցիայի հարց է, որովհետև կոդը պահանջել է ինչ-որ բան, ինչ ակտիվ իրականացումը չի առաջարկում։ 0-ն սերմավորման բողոքով միջավայրի հարց է, որովհետև գեներատորը բոլորովին չի կարողացել էնտրոպիա ստանալ։ Թիվն ինքնին երբեք չի ասում, թե որն է, և ֆունկցիայի անունը նույնպես չի ասում։
Երբ թաքնված սարքի հանգույցն է իրական պատճառը
Սահմանափակ ծառայությունը տեսնում է այլ ծառ, քան այն shell-ը, որում դուք մուտքագրում եք։ Chroot բանտերը, կոնտեյներային պատկերները և կարծրացված unit ֆայլերը սովորաբար ներկայացնում են /dev, որն ավելի քիչ հանգույցներ ունի, քան հոսթինը։ Եթե ձախողվող իրականացումը /dev/urandom-ը բացում է ուղու անունով, այդ տարբերությունը բավական է գործարկումը կոտրելու համար, մինչ հոսթն ինքը կատարյալ առողջ տեսք ունի։ Բանտից դուրս գոյություն ունեցող սարքը ոչինչ չի ապացուցում այն մասին, թե ինչ կարող է բացել բանտարկված գործընթացը։
Սակայն ոչ բոլոր պատահական ինտերֆեյսն է ուղի պահանջում։ Linux-ի getrandom համակարգային կանչը չի ընդունում ոչ ֆայլի անուն, ոչ ֆայլի դեսկրիպտոր, և դրա ձեռնարկի էջը նշում է, որ այդ հատկությունը օգտակար է հենց այնտեղ, որտեղ 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
Այդ ընթերցումները կատարեք նույն գործընթացի վրա, ոչ թե պատահաբար բաց shell-ի վրա։ Հոսթի /dev-ը չկապակցված գործընթացի տեսքի հետ համեմատելը սխալ կախվածության կրկնակի վերանորոգման ճանապարհն է։
Կախվածությունը ավելացրեք միայն այն ժամանակ, երբ կարող եք անվանել այն
Երբ ապացույցներն իսկապես նշում են ուղի, վերանորոգումը փոքր է՝ այդ մեկ ուղին հասանելի դարձրեք բանտի ներսում և մնացածը թողեք հանգիստ։ Մեկ հանգույցի bind mount-ը սովորաբար բավական է, և mknod-ը հանգույցի ստանդարտ major և minor համարներով նույն արդյունքն է տալիս այն տեղադրումներում, որտեղ mount-ը տարբերակ չէ։ Sandbox-ի ընդլայնումը, յուրաքանչյուր սիմվոլ սարքի հասանելիություն տալը կամ PrivateDevices-ի անջատումը թիրախային ուղղումը փոխանակում է մշտական անվտանգության ռեգրեսիայի հետ։
Էնտրոպիայի դեմոնը չի փոխարինում այդ վերանորոգմանը։ haveged-ի նման փաթեթները փոխում են, թե ինչպես է սնվում միջուկի ավազանը՝ նրանք չեն կարող ստեղծել ուղի, որը բանտարկված գործընթացին թույլատրված է բացել։ Մեկի տեղադրումը կարող է առողջության գրաֆիկը ավելի լավը դարձնել, մինչ բացելու կանչը դեռ ձախողվում է։ Առանձին պահեք երկու խնդիրները, հակառակ դեպքում հաջորդ խափանումը նորից կվերագրվի սխալ շերտին։
Ստուգեք գեներատորն ու թունելը առանձին
Վերագործարկումը միակ փորձն է, որ նորից օգտագործում է նույն կազմաձևը, նույն unit ֆայլը և նույն մեկուսացումը, որոնք առաջացրել են խափանումը։ Գործարկեք այն, ապա կարդացեք մատյանի ամենանոր գրառումները, ոչ թե ավելի վաղ գործարկումից վերցված նմուշ։
sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'
Այդ ելքի մեջ փնտրեք երկու առանձին բան՝ պատահական աղբյուրի մասին հաղորդագրության անհետացումը և թունելի՝ իր սովորական մեկնարկային հանգրվանին հասնելը։ Կրկին աշխատող գեներատորը վերացնում է մեկ լոկալ խափանում և ոչինչ չի ասում սերվերի ինքնության, հավատարմագրերի կամ երթուղավորման մասին։ Փորձարկեք դա նույն հաճախորդի կազմաձևով, որը նախկինում ձախողվել է, որպեսզի արդյունքը լինի համեմատելի, այլ ոչ թե պարզապես ավելի լավ։