VPN на минималках
— "Дима, сделай Алевтине Генриховне виртуальную машину, чтобы она могла изучать систему, и свяжись с ней для настройки подключения" - именно с такой задачи начинается процесс обучения нового сотрудника в нашей компании.
— "Ну сейчас начнется" - думаю я.
— “VPN настраивать не умею”, “У меня все зависло”, “По инструкции настроить не получилось” - подобные реплики от “бизнес-аналитика Алевтины Генриховны” слышно с завидной регулярностью.
Приходится связываться, подключаться одним из доступных способов, и настраивать всё самому. Хорошо если все работает с первого раза. Плохо, если в системе по какой-то причине не работают службы, драйверы минипортов, и т.д. Однако, подключаться и помогать всё равно приходится чаще, чем хотелось бы. С очередной Алевтиной Генриховной этот процесс мне изрядно надоел, и я стал думать над поиском решений, способных облегчить жизнь.
Диспозиция
Компания набирает сотрудников, которым предстоит работать с системой электронного документооборота. Сопровождать, обслуживать, расширять, модифицировать, "делать все хорошо" по требованиям клиентов. Новый сотрудник должен ознакомиться с системой, пройти вводный курс обучения. Если для бизнес-аналитиков, консультантов и продавцов можно выделить общий стенд (хотя и нежелательно, люди, работающие с одними и теми же данными имеют тенденцию мешать друг другу), то для разработчиков подобное невозможно. Главной причиной невозможности является специфичность решения вендора. Стенд разработки - это локальный экземпляр системы, плюс среда разработки (не Visual Studio, отдельное решение). Процесс разработки выглядит так:
разработчик пишет код, верстает формы в среде разработки;
проверяет и дебажит разработку в изолированном экземпляре системы, установленном вместе со средой разработки.
В данный момент среда разработки работает только под Windows. Возможность разместить двух и более разработчиков на одном сервере отсутствует, ввиду того, что отладка и проверка работоспособности разработки проводится фактически на одном экземпляре системы, и два разработчика, выполняя параллельный деплой, умножат результаты работы друг друга на ноль.
Таким образом получается, что для обучения сотрудника нужна отдельная виртуальная машина.
В процессе обучения сотрудники могут отваливаться по разным причинам. Кто-то потерял интерес, у кого-то были другие ожидания, и т.д.
Однако, предугадать конверсию на старте нельзя, и ресурсы выделяются всем. Процесс найма и обучения, как можно догадаться, событие не единоразовое. И все проблемы, связанные с настройками подключения проявляются постоянно.
В чем проблема
Собственно трудностей, мешающих жить, четыре:
Компетентность. Не все смогут настроить VPN. Даже по инструкции. Конечно, можно парировать тем, что проблема-то не в VPN, а в инструкции, однако бывают случаи, когда в системе не работают службы удаленного доступа, или вдруг начинаются проблемы с драйвером минипорта, или почему-то перестает работать L2TP.
Управление ресурсами и учетными данными. Для каждого пользователя нужно создать учетную запись (не давать же им общую, в самом-то деле). А главное не забыть эту учетную запись отключить по окончании процесса обучения. Много пользователей - много учетных записей, которые напрямую не связаны с конкретной виртуальной машиной.
Безопасность. Радикальным вариантом решения проблемы является проброс портов вовне. Есть постоянный IP и порт, подключайся на здоровье. Но такое решение повлечет за собой ряд последствий, минимальным из которых будут попытки подбора пароля, возможно по словарю. Однако столкнуться с 0day RCE тоже не хочется. Можно сказать, что этот вопрос настройки разрешения подключений только с доверенных IP в файрволле. Кто может гарантировать, что IP останется постоянным? Никто. А каждый раз добавлять в файрволл новый IP - путь в никуда.
Трудозатраты. Виртуальные машины с обучающимися вынесены в отдельный контур. Сетевая связность с основным контуром компании (1С, Git, База знаний, и т.д.) отсутствует. Хочется выделить пул ресурсов в виде готовых к работе виртуальных машин, предоставить способ подключения к ним, который будет одновременно простым, не требующим настройки и частого отвлечения на обслуживание, но в то же время достаточно безопасным, чтобы предоставлять его в массы, не опасаясь глобального взятия всего контура на абордаж.
Пути решения
Итак, что мы имеем?
Некоторое количество пользователей, которым нужно подключаться к виртуальным машинам по RDP;
Пользователи периодически испытывают проблемы с подключением, по разным причинам;
Необходимо создавать новые учетные данные для новых пользователей, и закрывать старые, неиспользуемые учетные записи;
Предоставить доступ нужно так, чтобы, с одной стороны, не выставлять ничего лишнего вовне, а с другой стороны - не усложнить процесс подключения.
Определившись с пожеланиями и ограничениями, возможно сформулировать список требований к будущему продукту:
Простота для конечных пользователей:
Не требуется установки и настройки.
Нет зависимости от механизмов ОС для создания\управления подключениями к VPN.
Удобство администратора:
Предоставление доступа для конечного пользователя должно быть максимально упрощено.
Для каждой виртуальной машины создается уникальная ссылка. Пользователь подключается к машине, перейдя по ссылке, для подключения не нужны никакие атрибуты (логины, пароли) кроме ссылки.
Если пользователь сменился (старый ушел, новый пришел) - ссылка генерируется заново, все старые ссылки перестают действовать.
Безопасность.
Так как решение будет спроектировано без использования традиционных VPN-сервисов и проброса портов, должны быть обеспечены условия:
Подключение возможно только с использованием ссылки.
Алгоритм генерации ссылки должен обеспечить уникальность ссылки, и сложность ее подбора.
По ссылке одновременно может подключиться только один пользователь.
Пользователь может подключиться только к той виртуальной машине, которая ассоциирована со ссылкой. Возможности сканирования IP и портов должны быть исключены.
Простыми словами
Администратор создает пул виртуальных машин, например 10 штук. Для каждой ВМ генерируется уникальная ссылка для подключения. Администратор выдает пользователям ссылки.
Пользователь переходит по ссылке, скачивает программу для подключения, нажимает кнопку “Подключиться”. Устанавливается защищенное соединение, автоматически запускается подключение к конечной ВМ по RDP, без необходимости вводить логин\пароль. Пользователь подключается к сеансу RDP, выполняет работу.
Как реализовать
Исходя из постановки задачи выделяем следующие компоненты:
Сетевой шлюз. Обеспечивает канал связи между клиентом и конечной ВМ.
На мой взгляд для реализации такой функциональности идеально подходит ssh-сервер, завернутый в docker-контейнер. Контейнер можно поднять по требованию, легко остановить и удалить. Каждому пользователю при подключении можно поднимать свой контейнер для проброса трафика на целевую ВМ, а с помощью настроек sshd можно лимитировать проброс портов.
Приложение для управления.
База с данными ВМ, ссылками. Управляет подключениями, разрешает или запрещает подключение. Управляет контейнерами с openSSH.
Клиентское приложение.
С помощью ссылки получает данные для установки ssh-туннеля, и подключения к конечной ВМ. Запускает mstsc, отслеживает процесс, сигнализирует о блокировке\разблокировке ВМ при старте\закрытии процесса mstsc.
Итог
Определившись с требованиями, и используемыми решениями, можно приступать непосредственно к реализации прототипа. В следующей статье разговор пойдет о выборе протоколов, фреймворков, и реализации серверной части системы.
И на последок хочу порекомендовать несколько бесплатных вебинаров от моих коллег из OTUS. Регистрация на мероприятия доступна по ссылкам ниже: