TOTP-портал: ввёл код — firewall открыл нужную группу
Цикл «Не светим лишнего». Выпуск 11.

Мы хотим простую пользовательскую механику: открыть страницу, ввести шесть цифр и получить доступ к заранее определённой группе ресурсов. Никакого нового сетевого интерфейса, клиента и борьбы двух VPN за маршруты.
После успешной проверки портал определяет внешний IP соединения и через контроллер добавляет его в динамический address-list на MikroTik. Firewall уже знает, что список access-monitoring разрешает HTTPS к Zabbix и Grafana, а access-dev — SSH и HTTPS только в тестовый сегмент.
Что такое TOTP
TOTP — Time-Based One-Time Password. Приложение вроде Google Authenticator и сервер имеют общий уникальный секрет. Из него и текущего временного шага вычисляется короткий код. В RFC 6238 типовой шаг — 30 секунд.
Важная оговорка: код не становится магически одноразовым после первого ввода. Пока действует временное окно, тот же TOTP технически можно отправить повторно, если сервер специально не помечает использованный шаг. Поэтому одного кода мало — после входа создаём нормальную серверную сессию, ограничиваем попытки и при необходимости запрещаем повторное использование конкретного шага.
Что хранит административная часть
Для каждого токена нужны:
- название и владелец;
- TOTP-секрет в зашифрованном виде;
- один или несколько профилей доступа;
- максимальная продолжительность;
- разрешённые часы или дата окончания;
- число одновременных сессий;
- состояние: активен, заблокирован, отозван;
- журнал выдачи и входов.
Админка должна быть доступна только из внутренней сети или отдельного управленческого контура. Публичной остаётся лишь маленькая страница входа и активной сессии.
QR-код регистрации показывает сам долговременный секрет. Его нельзя хранить в заявке, пересылать в общий чат и потом показывать повторно любому администратору. Нормальная схема: секрет генерируется, QR показывается один раз, пользователь подтверждает первый код, дальше виден только статус токена.
Как управлять MikroTik
Портал не должен ходить к RouterOS прямо из каждого веб-запроса. Лучше отделить worker, который получает решение контроллера и обновляет firewall по API.
API доступен только с IP этого worker по management-сети. Учётная запись имеет минимально возможные права. Сам API ни в коем случае не публикуется в Интернет ради портала.
На MikroTik уже существуют проверенные правила и списки. Worker может только добавить или удалить адрес в разрешённой группе с обязательным timeout и комментарием с ID сессии.
Плюсы
- ничего не устанавливается на пользовательскую машину;
- не конфликтует с существующим VPN;
- после открытия работают HTTP, SSH, RDP, WinBox и другие протоколы;
- токен связан с ролью, а не с произвольным правилом;
- доступ имеет срок и журнал;
- на целевых ресурсах сохраняется собственная авторизация.
Минусы
- firewall разрешает IP, а не браузер;
- общий NAT расширяет фактический круг сетевого допуска;
- смена внешнего адреса требует новой проверки;
- портал и worker становятся элементами безопасности;
- TOTP-секреты требуют серьёзного хранения;
- RouterOS API имеет довольно крупные права и нуждается в изоляции.
Где можно больно ошибиться
Брать IP из любого X-Forwarded-For. Доверяем только своему reverse proxy и точно знаем, какой источник увидит пограничный firewall.
Не ограничить перебор. Шесть цифр — миллион вариантов. Нужны rate limit на IP и токен, задержки, временная блокировка и журнал.
Разрешить произвольный список. Пользователь выбирает только готовый профиль, который назначен его токену.
Дать API полный доступ и выставить его наружу. Компрометация портала тогда сразу становится компрометацией маршрутизатора.
Сделать доступ бессрочным. Даже постоянный сотрудник должен запускать временную сессию, а не один раз навсегда открыть домашний IP.
Чего пока не хватает
Фиксированный timeout не знает, работает пользователь или давно закрыл ноутбук. Можно выдать час, но он закончит через десять минут. В следующем выпуске добавим WebSocket heartbeat: доступ существует, только пока жива авторизованная вкладка.
Ранее в цикле
- 5. Временный allow-list: открыть на час и не забыть закрыть
- 10. Авторизующий reverse proxy: доступ к приложению, а не к сети