Догађаји кука OpenVPN-а: зашто име и временска ознака нису кључ
Кука за прекид везе пријављује време повезивања, а не време прекида. У пару са корисничким именом може да оконча погрешну сесију; поседујте идентитет уместо тога.
Запис о прекиду стиже након што је друга веза под истим именом већ почела, и руковалац који ажурира најновији ред за тог корисника затвара погрешну сесију. Грешка није у поређењу временских ознака. Грешка је у претпоставци да име плус цела секунда идентификују једну сесију. Догађаји кука описују везе, а вези је потребан кључ који припада само њој.
Почните од тога шта променљиве прекида заиста значе. Тек тада избор идентификатора има смисла.
Шта кука за прекид заиста носи
У Community OpenVPN 2.6, референца за куке time_unix га дефинише као тренутак када се клијент повезао; поставља се пре него што се кука за повезивање покрене и не редефинише се када се кука за прекид касније активира. time_duration даје дужину те сесије у секундама, тако да је крај отприлике време повезивања плус трајање. Оба су целе секунде, и ниједно није тренутак када је ваша база података обрадила догађај. Управо раздвајање ова три времена омогућава корелацији да се одржи, уместо само да изгледа тачно током тестирања.
Ова аритметика заслужује да буде записана, јер је то једино крајње време које сама кука нуди. Кашњење обраде и разлике у часовницима између домаћина и даље остају изван ње.
Зашто очигледни пар није јединствен
Упаривање имена са временом повезивања сужава претрагу и још увек не идентификује сесију. Клијент може поново да се повеже у истој секунди, тако да две сесије могу да деле обе вредности. Две инстанце демона, или замена сервера која задржава исту конфигурацију, могу да произведу тај пар из различитих процеса. Адресе тунела се рециклирају из истог разлога, што их чини атрибутима сесије, а не идентификаторима за њу.
Режим отказа је тих. Касни прекид прве сесије поклапа се са најновијим редом и окончава доделу коју друга сесија још користи, па корисник доживљава случајан губитак приступа који није изазвао. Број редова који после изгледа тачно чини проблем теже уочљивим.
Одакле долази стабилан идентитет
Интерфејс за управљање додељује сваком клијенту идентификатор клијентске инстанце, и тај идентификатор је ограничен на инстанцу демона која га је издала. Употребљив спољни кључ комбинује стабилан идентификатор сервера, епоху која се мења када демон стартује, и тај клијентски ID. Епоха је важна јер се идентификатори рестартују са процесом, а голи ID процеса може касније поново да употреби нешто неповезано.
Променљиве окружења постављене унутар подређене скрипте за повезивање не путују до касније скрипте за прекид родитељског демона, јер се те скрипте извршавају као одвојени процеси са сопственим окружењима. Зато је генерисање UUID-а приликом повезивања половина решења. Страна прекида мора да уме да именује исти UUID, што значи да идентитет мора да живи негде где оба догађаја могу да стигну.
Учините повлачење условним и идемпотентним
Повлачите по власнику сесије, не по кориснику. Руковалац који брише било коју доделу која тренутно припада имену на крају ће обрисати погрешну, а једина одбрана је да проверите да је запис који се уклања запис који овај догађај описује.
Интерфејс за управљање прихвата један повезан клијент за управљање истовремено, зато се интегришите са оним који га већ поседује уместо да прикључите другог посматрача који се такмичи за исти сокет.
Рукујте поновљеним догађајима без двократне промене исхода, и чувајте неспарене догађаје за усаглашавање уместо да их одбацујете. Повратни позив за прекид има документоване услове животног циклуса и можда никада неће стићи после пада или тврдог заустављања, зато је дизајну потребан начин да представи сесију чији завршни догађај недостаје.
Тестирајте незгодне случајеве намерно: два поновна повезивања у једној секунди, две инстанце демона, повезивање чија обрада није успела, и рестартовање демона усред сесије. Кључ који преживи сва четири је кључ који вреди веровати.