Побеждает первая сессия: ограничение входов OpenVPN до вытеснения
Отклонить более поздний вход — не то же самое, что заменить старый. Решение должно приниматься до вытеснения одноимённой сессии, а проверка слота должна быть атомарной.
Политика, разрешающая одну сессию на учётную запись, кажется решённой, пока не придёт второй вход. Возможны два исхода: новый клиент заменяет текущую сессию либо текущая сессия сохраняет слот, а новому отказывают. Только второй вариант — это политика, где побеждает первая сессия. Клиентская опция, к которой прибегает большинство, включает параллельные подключения и потому такого результата не даёт.
За одной настройкой скрываются два договора
При отключённой параллельности второе подключение с тем же именем сертификата может вытеснить уже работающую сессию. Включение параллельности разрешает несколько сессий одновременно, что противоположно ограничению. Ни одно из состояний не является политикой отказа, поэтому решение нужно принимать совсем в другом месте.
Запишите договор до того, как что-либо внедрять: кому отказывают, какие доказательства идентифицируют текущую сессию и что происходит, когда сессия умирает без чистого отключения. Политику, которую никто так не сформулировал, позже нельзя проверить.
Вытеснение происходит до вашего хука подключения
В кодовом пути сервера 2.6 ранняя подготовка нового клиента удаляет существующие экземпляры с тем же именем, когда параллельность отключена. Это удаление происходит до запуска цепочки обработчиков подключения. Поэтому скрипт, который замечает дубликат и возвращает ошибку, отклоняет нового уже после того, как текущая сессия была сброшена, - ровно тот результат, который политика должна была предотвратить. Порядок обратных вызовов в upstream-реализации - единственный надёжный ответ для вашей сборки.
| Stage | Who can still refuse | Effect on the incumbent |
|---|---|---|
| Certificate check | Server trust configuration | None |
| Authentication decision | The authentication controller | None, because establishment has not run |
| Connect handler | A profile script | Already evicted in the same-name case |
| Post-establishment | Status tooling, monitoring | Both sessions already exist or one is gone |
Опрос файла состояния тоже не является воротами. Две попытки, пришедшие одновременно, могут обе увидеть пустой слот до того, как какая-либо его подтвердит, и обе продолжатся.
Перенесите решение в аутентификацию
Интерфейс управления может взять на себя решение об аутентификации после проверки сертификата. В такой схеме контроллер не наблюдатель: он получает каждый подключающийся экземпляр клиента и отвечает, разрешено ли этому экземпляру продолжать. Поскольку ответ приходит до установления, отказ оставляет текущую сессию нетронутой. Тот же канал сообщает об отключениях, и так контроллер узнаёт, что слот был освобождён законно.
Каждый новый экземпляр должен пройти через эти ворота, включая переподключения и любой путь, который повторно аутентифицируется без запроса. Ворота, до которых некоторые экземпляры никогда не доходят, ничего не защищают, и этот пропуск остаётся незаметным, пока кто-нибудь не попробует обход.
Токены могут пройти мимо ворот
После выпуска токена сервер может проверить его внутренне и пропустить внешнюю аутентификацию для этого соединения. Вызов управления никогда не происходит, поэтому проверка слота, реализованная только там, никогда не видит новый экземпляр. Такое поведение - удобство для пользователей и дыра в политике параллельности. Заставьте соединения с токеном проходить эквивалентную авторитетную проверку или отключите путь токена, когда политика требует решения по каждому соединению.
Не компенсируйте это безоговорочным приёмом каждого токена. Просроченный или недействительный токен всё равно должен завершаться ошибкой, и он должен терпеть неудачу через ту же точку решения, что и всё остальное.
Привяжите резервирование к экземпляру, а не к адресу
Адрес - слабая идентичность: переподключение с того же ноутбука может прийти с другого адреса, а скопированные учётные данные - с того же. Привяжите резервирование к экземпляру клиента, который назначает сервер, чтобы повторная аутентификация уже допущенного экземпляра распознавалась как владелец. Новый идентификатор экземпляра должен получить свой слот через решение побеждает первый, даже когда он предъявляет тот же токен.
Освобождайте только резервирование, принадлежащее неудачной попытке. Задержавшееся событие отключения от более старой попытки не должно очищать слот более нового владельца, поэтому освобождение называет экземпляр, а не учётную запись. После перезапуска контроллера согласуйте живые сессии, прежде чем кого-либо допускать, и применяйте то же правило на каждом шлюзе, который обслуживает учётную запись.
Отдельно решите, как восстанавливается действительно устаревший слот. Администратору нужен документированный способ очистить его, и этот путь не должен быть доступен пользователю, который просто нажимает переподключиться.
Проверьте важные пары: два почти одновременных входа, переподключение после чистого завершения, повторная аутентификация текущей сессии, отклонённый новый клиент и перезапуск контроллера. В каждом случае текущая сессия должна оставаться работоспособной, а новому нужно отказать без побочного ущерба для других учётных записей.