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