Архитектура и безопасность
Документ для тех, кто решает, пускать ли L7 в свою инфраструктуру: как устроена система, что она видит, а чего не видит, и что произойдёт в разных плохих сценариях.
1Компоненты
Расширение браузера. 38 КБ, ванильный JavaScript, без минификации и обфускации — код можно прочитать целиком. Управляет маршрутизацией через штатные механизмы браузера: PAC в Chrome и Proxy API в Firefox. Не требует прав администратора, не устанавливает драйверов, не меняет системные маршруты и DNS.
Шлюз. Бинарник 8 МБ на Go, без зависимостей и конфигурационных файлов. Все настройки и сертификаты получает от панели управления по защищённому каналу и применяет на лету. Состояние хранит локально, чтобы переживать перезапуски и потерю связи.
Панель управления (CP). Веб-интерфейс и API. Хранит конфигурацию, выдаёт настройки шлюзам и расширениям, ведёт учёт устройств и лимитов.
2Путь запроса
Браузер ──TLS──► Шлюз ──TLS──► Целевой сервер
│
└── незащищённые домены ──► напрямую в интернет- Расширение получает по токену список защищаемых доменов и правила маршрутизации.
- Браузер направляет запросы к этим доменам на шлюз методом CONNECT, остальные — напрямую.
- Шлюз проверяет подключение, резолвит имя собственным резолвером (учитывая переопределения IP и порта, заданные администратором) и устанавливает соединение с целевым сервером.
- Дальше шлюз только перекладывает байты между сокетами.
Ключевое следствие: маршрут выбирается по домену, а не глобально для браузера. Через шлюз идёт ровно то, что перечислено в токене.
3Идентификация устройств
Токен — это приглашение, а не удостоверение личности. Личностью в системе является устройство.
При установке расширение регистрируется и получает идентификатор устройства (dev_id) и секретный ключ. Они хранятся отдельно от токенов и не сбрасываются при очистке данных браузера — только при удалении расширения.
Каждый запрос к API сопровождается:
- идентификатором устройства
- временной меткой
- подписью HMAC-SHA256
Это даёт три эффекта:
API различает пользователей одного токена. Один токен, выданный трём аудиторам, — это три разных устройства с отдельной статистикой и отдельным отзывом.
Перебор токенов затруднён. Обратиться к API анонимно нельзя: нужен зарегистрированный dev_id с валидной подписью. Попытки перебора привязаны к конкретному устройству и обрываются по нему, а не по IP, который легко сменить.
Повторы запросов не проходят. Временная метка в подписи защищает от replay-атак.
4Что защищает токен
Пять символов в алфавите base58 (регистр значим) — это идентификатор доступа, а не единственный барьер. Даже зная токен, посторонний не получит доступа, потому что:
- обратиться к API можно только с зарегистрированного устройства с валидной подписью;
- количество активаций ограничено — когда лимит исчерпан, новые устройства не подключаются;
- токен может иметь окно активации, за пределами которого он не работает;
- токен может быть защищён паролем: конфигурация скачивается зашифрованной, без пароля не расшифровывается;
- каждое подключившееся устройство видно администратору и отзывается отдельно.
Токены с паролем начинаются с заглавного символа — это видно по написанию, поэтому пароль ожидается сразу.
Политики на уровне домена
Требования безопасности можно закрепить за самим ресурсом, а не за каждым токеном:
- Только защищённый токен — любой токен, включающий такой домен, обязан иметь пароль. Панель управления не даст создать его без пароля.
- Только приватная сессия — токен с таким доменом принудительно работает в приватном режиме расширения: при закрытии браузера токен и конфигурация забываются.
Это защита от человеческой ошибки: пометка ставится один раз на чувствительный ресурс и действует для всех будущих токенов, независимо от того, кто и в спешке ли их создаёт.
Политики применяются fail-closed, но без разрыва работающего доступа: добавить защищённый домен в незащищённый токен нельзя, а если политику включили позже — в существующих токенах домен становится выключенным, и включить его можно только после выполнения требования. Изменять политики домена вправе только владелец воркспейса и администратор; менеджеру это недоступно.
Отдельно домен можно скрыть из списка в расширении — доступ работает, но в интерфейсе пользователя ресурс не отображается. Полезно для технических доменов, к которым пользователь не обращается напрямую.
5Невидимость шлюза
Шлюз не отвечает никому, кроме зарегистрированных устройств, и не сообщает о себе ничего.
Уникальный адрес на устройство. Каждое устройство подключается к шлюзу по собственному имени хоста. В публичном DNS и в сертификате присутствует только wildcard — конкретные имена нигде не публикуются. Это важно из-за Certificate Transparency: сертификаты на каждое устройство означали бы публичный список всех устройств, wildcard такую утечку исключает.
Предавторизация по SNI. Шлюз проверяет имя хоста в TLS-хендшейке до всего остального. Если имя не ожидается, соединение сбрасывается: ни ServerHello, ни сертификата, ни TLS-alert. Тип alert сам по себе является отпечатком, поэтому он не отправляется.
Одинаковая реакция на любой мусор. Обычный HTTP-запрос и невалидный TLS получают один и тот же сброс соединения — определить по ответу, какой протокол ожидается на порту, нельзя.
Бан по IP. Источник неудачной пробы попадает в блокировку.
Что видит сканер: порт принимает TCP-соединение. Больше ничего — ни баннера, ни сертификата, ни кода ошибки.
6Шифрование трафика
Публичные сайты: сквозное шифрование. Шлюз выполняет маршрутизацию по SNI и не терминирует TLS. Сессия шифруется между браузером и вашим сервером; шлюз видит имя домена и объём переданных байт, но не содержимое. Расшифровать трафик он технически не может — ключей у него нет.
Внутренние сервисы по HTTP: терминация на вашей стороне. Если сервис работает без TLS (например, Grafana на 127.0.0.1:3000), шлюз ставится на ту же машину или в ту же сеть и терминирует TLS локально, обращаясь к сервису по петле или приватному адресу. Незашифрованный участок не покидает вашу машину или вашу сеть.
В обоих случаях открытый трафик не проходит по публичным сетям.
7Синхронизация настроек
Шлюзы получают настройки от панели управления по постоянному соединению.
Инкрементально. Передаются только изменения, а не полная конфигурация всех пользователей. Это делает применение быстрым независимо от размера установки.
На лету. Новые настройки применяются без перезапуска и без разрыва текущих соединений. Если пользователю добавили трафик в момент, когда он качает файл, загрузка не прервётся.
С сохранением состояния. Шлюз хранит конфигурацию локально и продолжает работать при потере связи с панелью управления — включая перезагрузку сервера.
8Отзыв доступа
Отзыв устройства или изменение лимитов доезжает до шлюзов за секунды и применяется немедленно: перезапуск браузера пользователю не поможет.
Важное ограничение. Если шлюз в момент отзыва недоступен для панели управления, изменение применится после восстановления связи. Автономность шлюзов — то, что защищает от простоя при проблемах на нашей стороне, но она же означает, что окно распространения отзыва равно времени восстановления связи. В обычных условиях это секунды.
9Сценарии отказа
Панель управления недоступна. Шлюзы продолжают работать с последней известной конфигурацией. Новые устройства подключить нельзя, существующий доступ сохраняется. Изменения настроек применятся после восстановления.
Шлюз недоступен. Защищаемые сайты не открываются у тех, кто ходит через этот шлюз. Остальной трафик браузера не затронут. Домены можно переключить на другой шлюз в панели управления.
Расширение удалено. Доступ прекращается, в системе ничего не остаётся. Повторная установка потребует новой активации токена.
Пользователь потерял устройство. Отзовите его dev_id — доступ прекратится, остальные пользователи того же токена не затронуты.
10Что мы видим и чего не видим
Видим:
- к каким доменам подключались устройства и когда
- объём переданного трафика
- идентификаторы устройств и статистику их активности
- события сканирования шлюзов (телеметрия защиты)
Не видим:
- содержимое трафика к публичным сайтам — оно зашифровано сквозным TLS
- пароли, куки, данные форм, содержимое страниц
- трафик к доменам, которых нет в токенах, — он вообще не проходит через нашу инфраструктуру
Не видим при self-hosted шлюзе: ничего из трафика вообще — он не проходит через нашу инфраструктуру ни в каком виде. Панель управления в этом случае обменивается со шлюзом только конфигурацией и статистикой.
Известные ограничения
Честный список, чтобы не тратить ваше время на проверку:
- Только HTTP/HTTPS в браузере. SSH, базы данных, доступ из CLI не поддерживаются. Клиент для TCP-over-HTTPS в планах.
- Шлюз должен быть доступен извне. Работа за NAT без проброса портов невозможна.
- ECH не используется. Браузеры не применяют Encrypted Client Hello к прокси-соединениям, поэтому наблюдатель на пути (провайдер, корпоративный DPI) видит имя хоста, по которому устройство подключается к шлюзу. Имя псевдонимно и без ключей устройства бесполезно.
- Один домен — один маршрут одновременно в пределах браузера.