Неуспех client-connect у OpenVPN-у: да ли је чишћење при disconnect загарантовано?
Одбијен клијент не поништава firewall правило нити записани запис. Упоредите уговор повратног позива са враћањем које ваш hook мора сам да изведе.
Када скрипта client-connect изађе са ненултим кодом, OpenVPN одбија клијента, а администратори обично претпостављају да ће одговарајућа скрипта client-disconnect све средити. Често се она никада не покрене, јер обрада disconnect зависи од тога шта је фаза connect успела да доврши. Третирање одбијања и враћања као једног механизма је оно што неуспешну пријаву претвара у исцурело firewall правило или у запис без власника. То су две одвојене обавезе, а само једна од њих је аутоматска. Прочитајте сопствену излазну путању hook-а пре него што оптужите сервер да је оставио стање.
Ненулти излаз одбија клијента; не поништава ваш рад
Излазни статус client-connect је одлука о пријему. Нула значи прихватити, све остало значи срушити инстанцу пре него што се потпуно успостави. Ништа у том уговору не проверава шта је скрипта већ учинила у спољном свету. Ако је скрипта додала iptables правило, записала ред или увећала бројач, те промене преживљавају одбијање.
Иста асиметрија важи за додатке, где се за једну инстанцу може извршити неколико connect функција. Каснији неуспех не поништава ретроактивно ранији успех, а ранија функција не може да сазна да је сестринска функција подбацила.
Одбијање је аутоматско, чишћење није
Приручник за OpenVPN 2.6 везује обраду client-disconnect за успешно довршену претходну обраду connect. Документовани изузетак покрива каскадне ланце: ако је један connect корак већ вратио успех, одговарајући disconnect кораци се ипак извршавају при рушењу инстанце, иако је каснији connect корак подбацио. Тај изузетак је узан и зависи од броја конфигурисаних повратних позива, зато вам тестирање једне shell скрипте не говори ништа о ланцу.
Мапирајте стварну конфигурацију пре него што дизајнирате око ње: која скрипта, који додатак и којим редоследом се извршавају. Табела испод наводи шта половично довршено подешавање оставља за собом.
| What the hook did before failing | What the client sees | What stays behind |
|---|---|---|
| Created a firewall entry | A rejection, with no tunnel | A rule matching an address nobody owns |
| Wrote a state row | A rejection, with no tunnel | A record of a session that never started |
| Allocated a tunnel address | A rejection, with no tunnel | An address marked busy until something releases it |
Сваки ред се завршава исто за клијента, а другачије за домаћина. Клијент не може да каже који се од њих догодио, па hook мора да поништи оно што је учинио пре него што врати статус неуспеха.
Надокнадите унутар скрипте која је подбацила
Проверите све што можете пре него што дотакнете дељено стање: поља сертификата, доступност адресе, групу којој клијент припада. Најјефтиније одбијање је оно које се догоди пре било какве доделе. Када подешавање обухвати неколико спољних операција, водите евиденцију које су довршене и поништите их обрнутим редоследом пре него што вратите статус неуспеха.
Конкретан случај: скрипта ствара firewall запис за сваког клијента, а затим не успева да упише ред стања који га описује. Грана која подбаци треба да уклони управо створени запис и затим изађе са ненултим кодом. Чекање на догађај disconnect који можда никада неће бити заказан јесте начин да правило надживи сесију којој је било намењено.
Учините надокнаду идемпотентном и са власником
Чишћење мора бити безбедно за двоструко извршавање и прецизно у погледу тога шта сме да избрише. Касни догађај из ранијег покушаја не сме да уклони доделу новије сесије само зато што обе деле заједничко име или рециклирану адресу тунела. Забележите конкретну ручку или идентификатор операције уз ресурс и бришите по том кључу, а не по имену. Трансакције базе података помажу само са сопственим променама базе; firewall правило изван те границе захтева изричит корак надокнаде.
Претпоставите да процес може да умре између промене и чишћења и додајте усклађивач који по распореду пореди спољно стање са списком прихваћених клијената.
Тестирајте три путање које се заиста разликују
Вежбајте три случаја: одбијање пре него што било шта буде додељено, одбијање после делимичне доделе и нормалну прихваћену сесију која се касније завршава. Та три дају различите линије дневника и различите остатке. Проверите спољно стање после сваког од њих, не само поруку о неуспеху клијента, јер је неуспех клијента очекивани исход у два од три случаја.
Забележите фазу hook-а, излазни статус и шта је додељено или ослобођено, без акредитива. Дневник hook-а који именује створени ресурс је оно што исцурело правило чини пронађивим шест месеци касније.