Привет, понадобилось мне сделать адекватный реверс сокс, но вот с сокетами я прям редко-редко сталкивался и соответственно мало что в них понимаю.
Для начала опишу архитектуру, можно её если что предлагать поменять если она неадекватная - буду благодарен только.
БК-сервер часть:
Начну с неё, потому что проблема лежит в бот-части, чтобы было понятнее. Примерно опишу, за технические опечатки сорри.
БК сервер асинхронно принимает соединения на 80 порт от ботов, и при наличии нового соединения (accept) открывает (listen) рандомный свободный порт на приём соединения от пользователя (user -> BC-server -> bot). При получении соединения на listening port юзер стороны все пакеты на него инкапсулирует в структуру которую маркирует ID этого соединения (за ID берется сокет), и пересылает инкапсулированные данные в соединение для бота. Ответ от бота пересылается обратно. Вся проблема возникает в том, что на стороне БК-сервера мы можем плодить сколько угодно сокетов принимая соединения через accept, но пакеты входящие от нескольких соединений (например mstsc любит плодить кучу соединений одновременно на один адрес, или браузер) мы передаем в одно единственное соединение бота, маркируя его в кастомный протокол где у нас идентифицируется номер соединения для мультиплексирования. Дальнейшую проблему опишу ниже в детальных пунктах
Начну с описания БК-сервера подробнее
1) БК-сервер открывает 80 порт на слушание в неблокирующем режиме через сокеты для приёма коннектов от ботов
В основном цикле:
2) неблокирующе опрашивает через accept порт 80, если есть соединение, то добавляет сокет соединения в списочек активных соединений от ботов
3) делает такой же accept на каждый активно открытый порт для приёма от user'а (если присутствует, при нулевой итерации этот пункт пропускается) и делает такую же операцию как в пункте 2 для него
4.1) производит попытку прочитать из каждого сокета соединений 80 порта - если соединение неавторизовано, то ожидает авторизации (по кастомному протоколу) и после прохождения присваивает ему уникальный порт и открывает его на прослушивание и приём соединений (то что описывается в пункте 3)
4.2) если сокет авторизован уже, то то что приходит от бота парсит ID соединения (которое описывалось выше) и делает send в соответствующий сокет юзверя (оперделяя его по ID так как ID соединения от бота совпадает с номером сокета) со стороны юзверя (который открывался на пункте 4.1)
5) парсит recv в цикле каждый сокет от юзверя и если там есть входящие данные, то пересылает их инкапсулируя в мультиплекс структурку с ID сокета соединения через send в конкретное соединение от бота
Бот часть:
1) Бот коннектится к БК-серверу, производит авторизацию
В цикле:
2) делает recv в ответ ему летят какие-то данные, каждый чанк данных промаркирован ID соединения
3) если там по проткоолу новое соединение проксирующее, то он соответственно делает соединение куда надо, ассоциируя это соединение с данным ID, ответ возвращает обратно в сокет с данным ID
соответственно в цикле так гоняет - входящие буфера пишет по ID ассоциированный с конкретным соединением, ответ инкапсулирует в структуру с таким же ID и шлет обратно
3.1) если это уже проксирование, то определяет по ID нужное соединение и шлет туда данные, ответ пересылает обратно
Проблема вся на пункте 2, 3, 3.1 Бот-части, которая вытекает из пункта БК-сервера 5
Заключается она в том, что множественные соединения (например, их может быть 3 от user -> BC-server -> client) все параллельно пишутся в одно единственное соединение с ботом. И так как нам заранее неизвестен размер отправляемого буфера (условно, проксируемое приложение может производить отправку какими-то чанками, как, например, браузер), то в входящем буфере на боте у нас будет рандом полнейший: блок от одного соединения, блок от другого, блок от первого и тд, и в каком порядке что и как это отправлять не совсем ясно.
Каким образом решить эту проблему? Может стоит от бота делать новое соединение обратно к БК-серверу как у нас прокси устанавливает новое соединение? И уже в это соединение делать общение. Или есть какие-то еще варианты?
Для начала опишу архитектуру, можно её если что предлагать поменять если она неадекватная - буду благодарен только.
БК-сервер часть:
Начну с неё, потому что проблема лежит в бот-части, чтобы было понятнее. Примерно опишу, за технические опечатки сорри.
БК сервер асинхронно принимает соединения на 80 порт от ботов, и при наличии нового соединения (accept) открывает (listen) рандомный свободный порт на приём соединения от пользователя (user -> BC-server -> bot). При получении соединения на listening port юзер стороны все пакеты на него инкапсулирует в структуру которую маркирует ID этого соединения (за ID берется сокет), и пересылает инкапсулированные данные в соединение для бота. Ответ от бота пересылается обратно. Вся проблема возникает в том, что на стороне БК-сервера мы можем плодить сколько угодно сокетов принимая соединения через accept, но пакеты входящие от нескольких соединений (например mstsc любит плодить кучу соединений одновременно на один адрес, или браузер) мы передаем в одно единственное соединение бота, маркируя его в кастомный протокол где у нас идентифицируется номер соединения для мультиплексирования. Дальнейшую проблему опишу ниже в детальных пунктах
Начну с описания БК-сервера подробнее
1) БК-сервер открывает 80 порт на слушание в неблокирующем режиме через сокеты для приёма коннектов от ботов
В основном цикле:
2) неблокирующе опрашивает через accept порт 80, если есть соединение, то добавляет сокет соединения в списочек активных соединений от ботов
3) делает такой же accept на каждый активно открытый порт для приёма от user'а (если присутствует, при нулевой итерации этот пункт пропускается) и делает такую же операцию как в пункте 2 для него
4.1) производит попытку прочитать из каждого сокета соединений 80 порта - если соединение неавторизовано, то ожидает авторизации (по кастомному протоколу) и после прохождения присваивает ему уникальный порт и открывает его на прослушивание и приём соединений (то что описывается в пункте 3)
4.2) если сокет авторизован уже, то то что приходит от бота парсит ID соединения (которое описывалось выше) и делает send в соответствующий сокет юзверя (оперделяя его по ID так как ID соединения от бота совпадает с номером сокета) со стороны юзверя (который открывался на пункте 4.1)
5) парсит recv в цикле каждый сокет от юзверя и если там есть входящие данные, то пересылает их инкапсулируя в мультиплекс структурку с ID сокета соединения через send в конкретное соединение от бота
Бот часть:
1) Бот коннектится к БК-серверу, производит авторизацию
В цикле:
2) делает recv в ответ ему летят какие-то данные, каждый чанк данных промаркирован ID соединения
3) если там по проткоолу новое соединение проксирующее, то он соответственно делает соединение куда надо, ассоциируя это соединение с данным ID, ответ возвращает обратно в сокет с данным ID
соответственно в цикле так гоняет - входящие буфера пишет по ID ассоциированный с конкретным соединением, ответ инкапсулирует в структуру с таким же ID и шлет обратно
3.1) если это уже проксирование, то определяет по ID нужное соединение и шлет туда данные, ответ пересылает обратно
Проблема вся на пункте 2, 3, 3.1 Бот-части, которая вытекает из пункта БК-сервера 5
Заключается она в том, что множественные соединения (например, их может быть 3 от user -> BC-server -> client) все параллельно пишутся в одно единственное соединение с ботом. И так как нам заранее неизвестен размер отправляемого буфера (условно, проксируемое приложение может производить отправку какими-то чанками, как, например, браузер), то в входящем буфере на боте у нас будет рандом полнейший: блок от одного соединения, блок от другого, блок от первого и тд, и в каком порядке что и как это отправлять не совсем ясно.
Каким образом решить эту проблему? Может стоит от бота делать новое соединение обратно к БК-серверу как у нас прокси устанавливает новое соединение? И уже в это соединение делать общение. Или есть какие-то еще варианты?
