Обратный websocket/http туннель данных на .NET + SignalR

 

Возникла необходимость организовать трафик к внешнему сервису из сегмента сети с ограничением на исходящие соединения. Этот внешний сервис работал одновременно со множеством tcp/udp сокетов. При беглом обзоре существующих утилит не обнаружил готовое решение инкапсуляции множества сокетов с поддержкой «обратного» соединения.

Решил сделать свое решение, основными требованиями которого являются:

  1. Использовать один белый IP адрес с одним tcp портом, по умолчанию 80 порт http.

  1. Транспорт туннеля по websocket или http, перфоманс или доступность. Идеально если будет автоматический выбор лучшего из доступных протоколов обмена.

  1. Туннелирование одновременно множества tcp и udp сокетов.

  1. Кросс-платформенное консольное приложение, конфигурируемое параметрами запуска.

 Исходя из пунктов 2 и 4 были выбраны .NET7 и библиотека SignalR. С этим набором я создал open-source проект, репозиторий https://github.com/viordash/TuToDataTunnel. В результате получилось два приложения TutoProxy.Server и TutoProxy.Client, в артефактах GitHub actions хранятся скомпилированные бинарники (x64), для linux и windows.

SignalR - это отличная библиотека для real-time транспорта данных, которая умеет автоматически выбирать протокол обмена: если недоступен websocket, то она переключается на http (long polling).

Приложение TutoProxy.Server - это сервер входящих подключений для клиентов туннелирования и также конечных tcp/udp клиентов. 

Аргументы его запуска:

Например, строка запуска входного туннелирования около 50-ти tcp/udp портов на три клиента будет выглядеть так:

TutoProxy.Server http://200.100.10.1:8088 --tcp=3389,8071-8073,10000-10010,20000-20010 --udp=5000-5010,7000-7010 --clients=Client0Linux,ClientSecLinux,Client3Win

 
Приложение TutoProxy.Client - это клиент туннелирования выходного трафика. 

Аргументы его запуска:

Например, строка запуска выходного туннелирования 5-ти tcp и 3-х udp портов будет выглядеть так:

TutoProxy.Client http://200.100.10.1:8088 127.0.0.1 --tcp=8071,10000,20004-20006 --udp=7000-7002 --id= Client0Linux.

Важно учесть то, что порты у различных TutoProxy.Client не должны пересекаться, т.е. каждый клиент обслуживает уникальный набор сокетов/портов.

Данное решение также может подойти для разворачивания веб-сервисов на «серых» IP, т.е. можно сэкономить на дорогостоящем VPS.

Известные на данный момент недостатки:

@viordash
03.01.2023 18:02 UTC
Первоисточник

Комментарии

@build_your_web
03.01.2023 13:15 UTC
+1

Неплохое упражнение по программированию, но впн проще.

@xmetropol
03.01.2023 13:32 UTC
0

FRP - fast reverse proxy, туннелирование TCP/UDP трафика, не то же самое делает?
https://github.com/fatedier/frp

@web3_Venture
03.01.2023 14:56 UTC
+2

Самое загадочное в .net это масштабирование SignalR, какие лимиты, что будет если одинаковые хабы будут на разных машинах, нужно ли масштабировать хабы, а не группы внутри одного хаба, какие лимиты и как паралелить если допустим есть 1 супер большая группа. Как при этом работать с fallover допустим если образ SignalR развернут в docker compose в N сервисов с внутренней случайном балансировкой от докер композа.

Ни разу нигде в интернатах не встречал такую статью. Хорошо бы чтобы ктото на хабаре такую сделал на конкретном примере.

@AR1ES
08.05.2023 17:18 UTC
0

Столкнулся с проблемой необходимости доступа между 2-мя ресурсами, скрытами за NAT-ом. Поднять отдельный сервер, к которому подключатся 2 клиента, чтобы сервер между ними маршрутизировал трафик - не проблема.
По тегу Reverse-tunneling предположил, что проект подойдёт мне, думая что не просто так там присутствует определение списка клиентов и идентификатора клиента, чтобы как раз по ним как-то маршрутизировать трафик. Но как я понял, всё же пока такиз возможностей нет.
Т.е. ищу что-то, что грубо говоря на клиентской машине начнёт слушать какой-то дополнительный порт, и весь трафик с этого порта будет маршрутизировать через сервер и клиента на другой стороне уже.

Вариант с ВПН не подходят, т.к. мне не нужен полноценный доступ в сети, с созданием виртуальных адаптеров. Может кто-то что-то такое видел?

@viordash
09.05.2023 09:21 UTC
0

идентификатор клиента это только "минимальная" аутентификация, чтобы на стороне сервера можно было бы отключить клиента.

Т.е. ищу что-то, что грубо говоря на клиентской машине начнёт слушать какой-то дополнительный порт, и весь трафик с этого порта будет маршрутизировать через сервер и клиента на другой стороне уже

нельзя эти запросы направить сразу на удаленный адрес? Не рассматривали вариант с локальной проксей?

09.05.2023 18:00 UTC
0

Нет, прямого доступа к удалённому хосту нет, т.к. оба хоста за NAT-ом. Локальный прокси тоже не поможет. Если не найду способа решения, то подумаю, как можно доработать Ваш проект, технически вроде ничего сложного в этом не должно быть.