Запіс аб адключэнні прыходзіць пасля таго, як другое злучэнне пад тым жа імем ужо пачалося, і апрацоўшчык, які абнаўляе самы новы радок для гэтага карыстальніка, закрывае не тую сесію. Памылка не ў параўнанні часовых метак. Яна ў дапушчэнні, што імя плюс цэлая секунда ідэнтыфікуюць адну сесію. Падзеі хука апісваюць злучэнні, а злучэнню патрэбны ключ, які належыць толькі яму.

Пачніце з таго, што насамрэч азначаюць зменныя адключэння. Толькі тады выбар ідэнтыфікатара набывае сэнс.

Што насамрэч нясе хук адключэння

У Community OpenVPN 2.6 даведнік па хуках time_unix вызначае як момант, калі кліент падключыўся; ён усталёўваецца перад запускам хука падключэння і не перавызначаецца, калі пазней спрацоўвае хук адключэння. time_duration дае працягласць гэтай сесіі ў секундах, таму канец прыблізна роўны часу падключэння плюс працягласць. Абодва — цэлыя секунды, і ніводзін не з’яўляецца момантам, калі ваша база даных апрацавала падзею. Менавіта раздзяленне гэтых трох часоў дазваляе карэляцыі трымацца, а не проста выглядаць правільна падчас тэсціравання.

Гэтую арыфметыку варта запісаць, бо гэта адзіны час заканчэння, які прапануе сам хук. Затрымка апрацоўкі і розніца гадзіннікаў паміж хастамі ўсё яшчэ застаюцца па-за ёй.

Чаму відавочная пара не ўнікальная

Спалучэнне імя з часам падключэння звужвае пошук і ўсё роўна не ідэнтыфікуе сесію. Кліент можа перападключыцца ўнутры той жа секунды, таму дзве сесіі могуць мець абодва значэнні. Дзве копіі дэмана або замена сервера, якая захоўвае тую ж канфігурацыю, могуць даць гэтую пару з розных працэсаў. Адрасы тунеляў перавыкарыстоўваюцца з той жа прычыны, што робіць іх атрыбутамі сесіі, а не ідэнтыфікатарамі для яе.

Рэжым адмовы ціхі. Позняе адключэнне першай сесіі супадае з самым новым радком і закрывае выдзяленне, якое другая сесія ўсё яшчэ выкарыстоўвае, таму карыстальнік адчувае выпадковую страту доступу, да якой не прычыніўся. Лік радкоў, які пасля выглядае правільным, робіць праблему цяжэйшай для выяўлення.

Адкуль бярэцца стабільная ідэнтычнасць

Інтэрфейс кіравання прызначае кожнаму кліенту ідэнтыфікатар кліенцкай копіі, і гэты ідэнтыфікатар абмежаваны копіяй дэмана, якая яго выдала. Працаздольны знешні ключ спалучае стабільны ідэнтыфікатар сервера, эпоху, якая змяняецца пры запуску дэмана, і гэты кліенцкі ID. Эпоха важная, бо ідэнтыфікатары перазапускаюцца разам з працэсам, а голы ID працэса можа пазней быць перавыкарыстаны чымсьці незвязаным.

Зменныя асяроддзя, усталяваныя ўнутры даччынага скрыпта падключэння, не перадаюцца ў пазнейшы скрыпт адключэння бацькоўскага дэмана, бо гэтыя скрыпты выконваюцца як асобныя працэсы са сваімі асяроддзямі. Таму генерацыя UUID падчас падключэння — гэта палова рашэння. Бок адключэння павінен мець магчымасць назваць той жа UUID, а значыць, ідэнтычнасць павінна жыць там, куды могуць дабрацца абедзве падзеі.

Зрабіце закрыццё ўмоўным і ідэмпатэнтным

Закрывайце па ўладальніку сесіі, а не па карыстальніку. Апрацоўшчык, які выдаляе любое выдзяленне, што зараз належыць імені, рана ці позна выдаліць не тое, і адзіная абарона — праверыць, што запіс, які выдаляецца, ёсць запісам, які апісвае гэтая падзея.

Інтэрфейс кіравання прымае аднаго падключанага кліента кіравання за раз, таму інтэгруйцеся з тым, хто ўжо валодае ім, замест таго каб далучаць другога назіральніка, які спаборнічае за той жа сокет.

Апрацоўвайце паўторныя падзеі, не змяняючы вынік двойчы, і захоўвайце няспароненыя падзеі для ўзгаднення, а не адкідвайце іх. Зваротны выклік адключэння мае дакументаваныя ўмовы жыццёвага цыклу і можа ніколі не прыйсці пасля збою або жорсткага спынення, таму дызайну патрэбен спосаб прадставіць сесію, падзея заканчэння якой адсутнічае.

Праверце нязручныя выпадкі наўмысна: два перападключэнні ўнутры адной секунды, дзве копіі дэмана, падключэнне, апрацоўка якога не ўдалася, і перазапуск дэмана ў сярэдзіне сесіі. Ключ, які вытрымлівае ўсе чатыры, варты даверу.

Падобныя артыкулы