Heartbeat: firewall открыт, пока жива вкладка
Цикл «Не светим лишнего». Выпуск 12.

Обычный временный доступ живёт по часам. Выдали на два часа — значит firewall будет открыт два часа, даже если человек закончил через десять минут.
А можно привязать lease не только ко времени, но и к живой браузерной сессии. После TOTP пользователь попадает на страницу «Доступ активен». Страница держит WebSocket с порталом. Пока соединение существует, контроллер регулярно продлевает короткую запись на firewall.
Закрыли вкладку — доступ снимается. Ноутбук уснул, сеть пропала, браузер завершился аварийно — lease не продлился и сам истёк.
Как подобрать интервалы
Практичная отправная точка:
- сервер проверяет живость WebSocket или получает приложение heartbeat каждые 15–20 секунд;
- запись firewall живёт 60–90 секунд;
- два пропуска дают предупреждение;
- через три-четыре пропуска сессия считается потерянной;
- есть абсолютный максимум, например восемь часов;
- кнопка «Закрыть доступ» отзывает сессию сразу.
Слишком короткий lease начнёт раздражать при любом мобильном провале. Слишком длинный убивает сам смысл heartbeat.
Лучше опираться не только на JavaScript-таймер фоновой вкладки: браузеры умеют их замедлять ради батареи. Сервер должен контролировать состояние WebSocket, протокольные ping/pong и время последнего подтверждения.
Несколько пользователей за одним NAT
Представим офис подрядчика. С одного публичного IP открыты две вкладки: у инженера доступ к камерам, у администратора — к мониторингу. Потом инженер закрывает свою вкладку.
Нельзя просто удалить этот IP из всех списков. Контроллер должен считать активные сессии отдельно и вести reference counting по ключу вроде:
пограничный шлюз + внешний IP + группа доступа.
Для access-cctv счётчик стал нулём — удаляем адрес только из CCTV-группы. Для access-monitoring остаётся единица — доступ администратора продолжает жить.
Если два пользователя с одного IP имеют одну роль, закрытие первой сессии уменьшает счётчик, но запись удаляется только после завершения второй.
Что происходит при смене IP
Мобильная сеть или другой VPN могут поменять внешний адрес. WebSocket обычно оборвётся. Автоматически переносить разрешение на новый IP опасно: лучше попросить повторное подтверждение TOTP или хотя бы явное действие в уже доверенной сессии.
Старый адрес при этом должен быстро исчезнуть по короткому lease.
Плюсы
- доступ живёт ровно во время работы;
- ничего не устанавливается;
- не меняются маршруты и DNS;
- подходит любым протоколам после открытия;
- короткий lease обеспечивает fail closed;
- можно показать пользователю понятный статус и кнопку отзыва.
Минусы
- IP остаётся общей сетевой идентичностью;
- общий NAT требует аккуратного учёта сессий;
- вкладку надо держать открытой;
- мобильные браузеры и энергосбережение могут рвать соединение;
- кластер портала требует общего хранилища сессий;
- логика отзыва сложнее обычного timeout.
Где можно больно ошибиться
Удалить доступ при закрытии одной вкладки, не проверив другие. Получим случайные обрывы у людей за одним NAT.
Доверять событию unload. Браузер не обязан успеть отправить его при падении или сне. Истинная страховка — короткий timeout на firewall.
Продлевать lease напрямую каждым heartbeat. При сотнях вкладок API маршрутизатора будут дёргать постоянно. Портал обновляет состояние в Redis/БД, а worker синхронизирует firewall с разумным интервалом.
Оставить established-соединения. Проверяем allow-list до общего accept established,related либо точечно чистим connection tracking при отзыве. Защищаемый трафик исключаем из FastTrack, если нужен немедленный разрыв.
Fail open при падении портала. Правило на firewall всегда имеет короткий timeout. Если контроллер умер, новые сессии не выдаются, старые естественно исчезают.
Считать WebSocket вторым фактором. Он подтверждает живость браузерной сессии, но не подписывает каждый SSH-пакет. На ресурсах остаётся своя авторизация.
Где эта схема особенно хороша
Временный доступ подрядчиков, dev-контуры, мониторинг, камеры, редкие административные панели — то есть всё, что желательно вообще не показывать без активного человека. Для особо опасных RDP и SSH можно пойти дальше и не открывать их напрямую даже после heartbeat, а проводить через web-bastion.
Ранее в цикле
- 5. Временный allow-list: открыть на час и не забыть закрыть
- 11. TOTP-портал: ввёл код — firewall открыл нужную группу