Де має бути місячна квота трафіку на обліковий запис OpenVPN
Квота, яка скидається під час кожного перепідключення, не є обмеженням. Стежте за витратою за обліковим записом, списуйте кожну різницю байтів один раз і робіть вичерпання блокуванням допуску.
Квота, яка скидається щоразу, коли тунель перепідключається, не є обмеженням, і саме це виходить, коли лічильник байтів прикручують до сервера VPN без місця для збереження стійкого стану. Лічильник належить сеансу; квота належить людині або договору на пристрій. Уся складність функції походить із цієї невідповідності, тому перевірки нижче стосуються того, де живе стан і якому шару дозволено ухвалювати рішення.
Прив'яжіть квоту до облікового запису, а не до тунелю
Почніть із того, щоб назвати суб'єкт квоти. Одна людина може мати три сертифікати пристроїв, і жоден із них не повинен отримувати незалежний місячний бюджет лише тому, що вони автентифікуються окремо. Стабільний ідентифікатор облікового запису, який переживає перепідключення, нові адреси тунелю й переїзд на другий шлюз, — єдиний якір, який може використовувати квота. Спільне ім'я сертифіката працює таким ключем лише тоді, коли ваша політика випуску гарантує один обліковий запис на ім'я.
Призначена адреса тунелю ніколи не є відповіддю. Адреси перевикористовуються, пули спільні, і той самий обліковий запис може з'явитися двічі на двох шлюзах тієї ж хвилини. Якщо реєстр спирається на адресу, відключення й повторного підключення достатньо, щоб знову наповнити бак.
Записуйте на кожен сеанс достатньо, щоб арифметика була перевірюваною: обліковий запис, розрахунковий період, екземпляр шлюзу, ідентичність сеансу, останні спостережені лічильники та затверджений підсумок. Включіть покоління запуску демона в ідентичність сеансу, бо перезапущений сервер повторно використовує ідентифікатори клієнтів, і наївне зіставлення успадкувало б попередню базову лінію.
Зафіксуйте одиницю, напрямок і межу скидання
Чотири визначення треба закріпити письмово до початку будь-якого збору. Чи квота рахує байти, які клієнт надсилає, які отримує, чи суму обох? Гігабайт — це 10^9 байтів чи 2^30? О котрій місцевій годині та в якому часовому поясі перемикається період? І що саме вимірює лічильник, зважаючи на те, що накладні витрати тунелю й повторні передачі включені, а розмір файлу застосунку та рахунок постачальника — ні?
Жоден із цих виборів не є помилковим, але реалізація та число, яке бачить клієнт, мають збігатися. Дві половини однієї системи, які розходяться в GiB або в перемиканні, що відбувається опівночі UTC замість місцевого часу, породжують саме той тип звернення, який підриває довіру до всієї квоти.
Перетворіть підсумки байтів на одну списану різницю
Інтерфейс керування повідомляє періодичні рядки BYTECOUNT_CLI, які несуть ідентифікатор клієнта та накопичені підсумки байтів у кожному напрямку, а команда bytecount задає, як часто вони надходять. З погляду сервера отримане число рахує байти, надіслані клієнтом, а надіслане число рахує байти, доставлені йому. Задайте інтервал таким, щоб реєстр міг його засвоїти; дуже короткий інтервал купує точність, якої ви насправді не отримуєте.
Одне обмеження формує весь дизайн: сокет керування приймає єдине керуюче з'єднання. Експортер моніторингу, графічний інтерфейс і ваш контролер не можуть відкрити кожен своє. Вирішіть, який процес володіє каналом, і дозвольте іншим читати стан із нього, бо цей інтерфейс дає адміністративні дії й у будь-якому разі не повинен виставлятися за межі хоста.
rx_delta = sample.rx_now - session.prev_rx
tx_delta = sample.tx_now - session.prev_tx
charge = rx_delta + tx_delta
# same transaction:
ledger.total += charge
session.prev_rx, session.prev_tx = sample.rx_now, sample.tx_now
Фіксуйте нові базові лінії та приріст витрати разом, щоб повторне відтворення вибірки нічого не списувало замість подвійного списання. Лічильник, що рухається назад, — це сигнал, а не борг: він означає, що сеанс було замінено або демон перезапущено, і правильна відповідь — узгодити ідентичність сеансу, а не зарахувати від'ємну суму.
Шлях відключення потребує такої ж обережності. Якщо завершальна подія несе підсумки кінця сеансу, списуйте лише різницю з останньої затвердженої вибірки. Додавання повного підсумку після того, як періодичну вибірку вже списано, — найпоширеніший подвійний облік у саморобних системах квот. Сеанси, що перетинають межу періоду, також потребують правила, бо один підсумок не несе інформації про те, коли байти перетнули опівніч.
Вичерпання має відмовляти в допуску, а не лише вбивати тунель
Коли обліковий запис досягає своєї межі, мають статися дві речі: наявні сеанси завершуються, а нові відхиляються. Протокол керування надає client-kill за ідентифікатором клієнта, що вирішує першу половину, якщо ви перелічите кожен живий сеанс облікового запису, а не вбиватимете єдину адресу, яку випадково помітили.
Друга половина — це місце, де дизайни квот зазнають невдачі. Саме лише вбивство — це гонка з циклом перепідключення клієнта, який охоче повернеться за кілька секунд. Допуск має звертатися до спільного реєстру, а в розгортанні з кількома шлюзами ця перевірка не може бути файлом на кожній машині. Кожен екземпляр, здатний прийняти вхід, має бачити той самий вичерпаний стан.
Перепідключення на основі токена заслуговують на власну перевірку. OpenVPN 2.6 може перевіряти токен сеансу внутрішньо за допомогою auth-gen-token, пропускаючи зовнішній виклик автентифікації, який ваш контролер використовував для забезпечення межі. Тому все ще дійсний токен доводить ідентичність, а не залишок квоти, і кожен новий екземпляр клієнта все одно має звертатися до реєстру. Якщо натомість увімкнути management-client-auth, контролер стає автентифікатором і успадковує обов'язок самому аналізувати стан сеансу та відхиляти прострочені або недійсні токени.
Прийміть перевищення, яке створює вибірка
Періодичне спостереження плюс відключення дають вам квоту за вибіркою з відомим допуском. Клієнт може перевищити приблизно на один інтервал звітності плюс час, потрібний контролеру для реагування, а паралельні сеанси на одному обліковому записі множать це вікно. Скажіть це в інтерфейсі замість того, щоб рекламувати точне відсікання на останньому байті, яке ви не можете забезпечити.
Справжня жорстка стеля — це інша інженерна задача: забезпечення всередині шляху пересилання, прив'язане до одного й того ж облікового запису протягом сеансів. Швидше читання лічильників — не те саме, і воно не витримує клієнта, який просто відкриває більше тунелів.
Перед розгортанням проженіть приймальні випадки, які ламають наївні реалізації: повторні перепідключення, два пристрої одночасно, перезапуски контролера й шлюзу, втрачена подія відключення, перемикання періоду посеред сеансу та спроба перепідключення токеном одразу після вичерпання. Потім визначте режим відмови для перебоїв в обліку. Стійкий реєстр захищає записану витрату; він не може воскресити спостереження, які так і не надійшли, і клієнт заслуговує знати, у якій із цих двох ситуацій він перебуває.