You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
7.4 KiB
139 lines
7.4 KiB
МОДУЛЬ И МОСТ VPN
|
|
ТЕХНИЧЕСКОЕ ЗАДАНИЕ
|
|
|
|
|
|
ГЛОССАРИЙ
|
|
Точка - в соединении Peer-to-Peer, одна из точек соединения. Локальная - та что ближе к нам; удаленная - та что дальше от нас.
|
|
Мост - в данном контексте, это сервер-посредник, или backconnect-сервер, коммутирующий VPN-соединения между собой.
|
|
|
|
|
|
ЦЕЛЬ
|
|
|
|
Разработка комплекса, аналогичного по функциям TeamViewer в режиме VPN, состоящего из трех частей:
|
|
- модуль на машине А, к которой мы хотим подсоединиться (дальний конец);
|
|
- VPN-клиент на машине Б, с которой мы хотим подсоединиться к машине А и всей её локальной сети (локальный конец);
|
|
- VPN-мост В, который принимает входящие VPN-соединения от А и Б и маршрутизирует их между собой (маршрутизатор, хаб).
|
|
|
|
Смысл использования VPN-моста в том, что машина А как правило находится за NAT/файрволлом и напрямую к ней не подрубиться.
|
|
А также потому, что могут быть закрыты входящие и исходящие TCP-порты, и поэтому нужно использовать порты наподобие 80 и 443
|
|
для исходящих соединений.
|
|
Потому соединение происходит так:
|
|
- А соединяется с В
|
|
- Б соединяется с В
|
|
- В пробрасывает маршруты между локальными точками А и Б таким образом, что Б видит А и её сеть, но не наоборот.
|
|
|
|
Акцент здесь не столько на VPN, как на маршрутизацию. Нужен УДОБНЫЙ способ присоединиться к удаленной сети.
|
|
Но VPN тоже нужен, т.к. незакрытый шифрованием трафик может резаться файрволлами и DPI-фильтрами.
|
|
|
|
|
|
МОДУЛЬ: РЕАЛИЗАЦИЯ
|
|
|
|
Модуль оформляется по правилам из документа "module_HOWTO".
|
|
У модуля единственный конфиг с именем "vpnsrv".
|
|
Содержимое конфига - простой текст, разделитель строк \r\n.
|
|
В строке один адрес/имя сервера в формате address:port или hostname:port.
|
|
Это адрес VPN-моста В.
|
|
|
|
Предполагается, что модуль работает с правами администратора.
|
|
|
|
При старте, модуль действует так:
|
|
- дожидается получения конфига с адресами моста
|
|
- случайным перебором находит рабочий мост (к которому удалось открыть соединение)
|
|
- если нет рабочих мостов, выдает событие "VPN bridge failure" и далее запрашивает собственную выгрузку событием "WantRelease".
|
|
- создает новое VPN-соединение к мосту В, используя штатные средства винды ("Центр управления адаптерами и общим доступом" - "Подключиться к сети").
|
|
Логином к соединению служит ParentID (см. ParentInfo в "module_HOWTO"), паролем - ParentGroup.
|
|
- запускает VPN-соединение к мосту В
|
|
- периодически проверяет статус соединения (можно простым пингом на адрес удалённой точки А)
|
|
- при закрытии соединения, восстанавливает его
|
|
- при выгрузке модуля вызовом Release(), завершает соединение и удаляет его из системы.
|
|
|
|
Вообще, предлагается использовать встроенный в Windows VPN-клиент. Но нужно найти способ подавить всплывающие уведомления (balloons)
|
|
из системного трея, при соединении/отсоединении.
|
|
Но здесь решение за разработчиком. Штатный клиент предлагается потому, что он уже есть в ОС; если есть способ создать легковесный VPN-клиент,
|
|
занимающий в готовом виде до 1 мегабайта и являющийся одной .dll (вместе с модулем), то это тоже допустимый вариант.
|
|
|
|
|
|
МОСТ: РЕАЛИЗАЦИЯ
|
|
|
|
Предположительно, можно организовать мост на OpenVPN.
|
|
Вопросы вызывает маршрутизация.
|
|
С большой долей уверенности, у машин А из разных организаций будут повторяющиеся адреса подсетей (192.168.0.х, 192.168.1.х, 10.0.х.х итд).
|
|
То же самое возможно и для клиентов Б, находящихся за NAT.
|
|
Поэтому, если к мосту подключится одновременно два и больше независимых клиента (Б1, Б2) и модуля (А1, А2), велика вероятность коллизии в маршрутизации между подсетями.
|
|
Наивное решение - запретить работу более одной пары А/Б.
|
|
Нужно найти способы обойти эту проблему.
|
|
|
|
Предполагается, что есть HTTP API для управления мостом, кроме OpenVPN.
|
|
|
|
В API есть следующий вызов:
|
|
|
|
GET /api/session/ParentID/ParentGroup HTTP/1.1
|
|
|
|
Здесь ParentID/ParentGroup - идентификаторы (ИД) модуля А.
|
|
В ответ мост посылает открытым текстом клиентский конфиг OpenVPN для клиента Б, с помощью которого можно соединиться с парным ему модулем А.
|
|
|
|
При обработке запроса, мост:
|
|
- запоминает ИД модуля А и заносит ИД в качестве корректного логина/пароля со сроком жизни в 3600 секунд (настройка)
|
|
- генерирует сеансовый логин/пароль для парного клиента Б со сроком жизни в 3600 секунд (настройка)
|
|
- генерирует конфиг OpenVPN для для парного клиента Б и отдает его вместе с HTTP-кодом 200
|
|
- если сгенерировать конфиг OpenVPN невозможно из-за недостатка данных (например, неизвестен адрес подсети модуля А, и нельзя форсировать маршрут к его подсети),
|
|
мост запоминает запрос и отдает его номер (квитанцию) клиенту, до уточнения данных, вместе с HTTP-кодом 202 Accepted
|
|
- HTTP-клиент периодически опрашивает готовность запроса с тем же самым URI GET /api/session/ParentID/ParentGroup HTTP/1.1
|
|
и анализирует код ответа:
|
|
200 - ответ готов
|
|
204 - в обработке
|
|
40* - ошибка обработки
|
|
50*
|
|
|
|
HTTP API следует защитить простой защитой от несанкционированного доступа - скорей всего Security by obscurity - сложным неиндексируемым путем к API,
|
|
либо HTTP Basic Auth.
|
|
|
|
Таким образом, мост несет следующие функции:
|
|
|
|
1. авторизация модуля
|
|
- Модуль должен указывать ParentID/ParentGroup в качестве логина и пароля на соединение; мост должен авторизовать модуль.
|
|
Мост получает список актуальных логинов/паролей и время их жизни в секундах по HTTP API.
|
|
Допустимо авторизовать только соединения с паролями из этого списка.
|
|
2. авторизация клиента
|
|
- для клиента, мост генерирует сеансовый логин/пароль, а также конфиг клиента для OpenVPN и отдает их через управляющее API.
|
|
|
|
|
|
ПОЛЬЗОВАТЕЛЬСКИЙ СЦЕНАРИЙ
|
|
|
|
Я, как пользователь, зашел в темную админку, выбрал клиентскую сессию с КОНКРЕТНЫМ ID и группой, от имени которого я хочу работать.
|
|
Я нажал в панели кнопку VPN.
|
|
|
|
За кадром, на дальнем конце (А) запустился модуль VPN, получил конфиг с адресом моста и поднял к нему VPN-соединение, ЗАЛОГИНИВШИСЬ со своим ID и группой.
|
|
Так мост знает, кто к нему подсоединился - ему это нужно для поиска пар соединений А и Б.
|
|
Тем временем темная админка дернула веб-бекенд моста по REST API, запросив конфиг для только что поднятого соединения.
|
|
Указав ID и группу бота при этом.
|
|
Мост сгенерировал сеансовый логин-пароль для парного клиентского VPN-соединения, и сгенерил временный OpenVPN-конфиг (простой текстовый файл)
|
|
для парного соединения. И отдал его в ответ на запрос по REST API. Темная админка отдает конфиг пользователю.
|
|
Пользователь получает этот конфиг и подсовывает его клиенту OpenVPN.
|
|
Подымается парное соединение со стороны пользователя на мост.
|
|
Мост может связать пару соединений - конечное (А-В) и пользовательское (Б-В), потому что он знает как ID и группу бота,
|
|
идентифицирующие А-В, так и сеансовый пароль юзера, идентифицирующий Б-В. Мост провешивает маршрут в таблице маршрутизации ОС.
|
|
Доп.маршруты для дальних концов пары соединений уже были отданы при установке соотв.соединений.
|
|
|
|
|
|
ИНСТРУКЦИЯ ПО ИСПОЛЬЗОВАНИЮ МОДУЛЯ
|
|
|
|
1. Заходим в леро, выбираем интересную нам сессию
|
|
2. Выполняем
|
|
push_back
|
|
код команды 62
|
|
параметры команды
|
|
vpnDllstart
|
|
3. Ожидаем запуска модуля (смотрим в леро сообщения от модуля)
|
|
2020-01-16 13:25:58 vpnDll net flyAgaric Can't connect to 173.232.146.30, error 718
|
|
2020-01-16 13:25:59 vpnDll net flyAgaric VPN bridge failure
|
|
|
|
|
|
алгоритм тестирования такой
|
|
1. запускаем софт на тестовой машине, даем ему развернуться
|
|
2. открываем его страничку в админке леро
|
|
3. запускаем команду push back: 62 vpnDll start
|
|
4. ждем пока модуль отреагирует и смотрим в логе админки как он отработает
|
|
5. параллельно смотрим что происходит на экране
|
|
6. ну и ищем в админке http:///admin/index.php?r=vpn%2Findex сессию, которую открыл модуль
|
|
короче говоря, простой тест - модуль работает, если ты в леро его запустил командой 62 vpnDll start и получил сессию в админке впн
|