Исходник [RakSamp Lite] Фикс работы через SOCKS5 прокси

Софтик Инквизитор

Участник
Автор темы
19
92
Фикс прокси для RakSAMP Lite

Всем привет. Короче долго мучался с тем что раксамп через socks5 не заходит на сервер. Пишет Auth OK, Connection succeeded, а потом сразу Connection attempt failed и так по кругу. Прокси при этом живой, query через него отвечает. Полез в ехе смотреть что там с прокси, нашел несколько косяков, написал луа скрипт который их правит.

Что было не так:

1. При UDP ASSOCIATE раксамп отправляет прокси адрес игрового сервера, хотя по RFC 1928 там должен быть адрес клиента (откуда он будет слать пакеты). В итоге прокси просто выкидывает все наши пакеты. Теперь шлется 0.0.0.0:0, т.е. принимай с любого адреса.

2. Некоторые прокси в ответе отдают адрес релея 0.0.0.0, это значит "шли на мой ip". Раксамп реально слал на 0.0.0.0) Теперь если пришли нули, подставляется ip самой прокси.

3. Самое главное, из за чего не заходило. Раксамп при коннекте шлет запрос раз в 150мс и после 6 попыток сам себе генерит ID_CONNECTION_ATTEMPT_FAILED. То есть на все рукопожатие меньше секунды. В обычном ракнете там 1000мс. Через прокси с пингом 300-400 два обмена с куки просто не успевают, поэтому и заходило через раз. Поставил 1000мс как в оригинале.

4. Еще нашел что перед коннектом раксамп отдельным сокетом шлет серверу query пакет напрямую, мимо прокси. То есть сервер видит твой реальный ip. Тоже вырезал.

Как работает
Скрипт через ffi патчит код прямо в памяти процесса, сам ехе не трогается.Перед патчем сверяются оригинальные байты, если у тебя другая версия раксампа то он просто ничего не тронет.

Установка
Кидаете !!proxy_udp_patch.lua в scripts, два восклицательных знака чтобы грузился первым. В консоли должно быть 5 строк с ok:
Код:
[proxy-patch] udp associate dst: ok
[proxy-patch] relay address: ok
[proxy-patch] connect retry interval: ok
[proxy-patch] direct query: ok

Важно
Проверял на RakSAMP Lite от 18.04.2022.

Кому интересно глянуть в иде:
Код:
0x45BED2 - UDP ASSOCIATE
0x45BF4F - разбор ответа прокси
0x40BA0C - recvfrom
0x40BCFD - интервал повтора коннекта
0x40387E - query мимо прокси
0x419060 - отправка пакетов

upd: По совету @AdCKuY_DpO4uLa убрал хардкод 1000мс. Теперь скрипт сам проверяет пинг до прокси по времени socks5-хендшейка и ставит интервал повтора как пинг+150+небольшой разброс. До первого замера остается 1000 по дефолту.
 

Вложения

  • !!proxy_udp_patch.lua
    3.3 KB · Просмотры: 68
Последнее редактирование:

AdCKuY_DpO4uLa

Адский дрочер
Друг
425
915
Красавчик, мне когда сокс сервер отдавал нули в качестве адреса, на который слать трафик, я думал, что он просто не воркает и обрубал коннект. Сколько же сотней проксей я мог бы в свое время заюзать параллельно...
А вообще, можешь замерять средний пинг между соксом и клиентом и вместо хардкода в 1000 мс пихать туда средний_пинг+150+небольшая погрешность в пределах 10-20% процентов. Выглядеть будет куда красивее и лаконичнее, да и можно будет срать ботами с полудохлых проксей с пингом под миллиард, а потом просто подделывать пинг (до тех пор, пока разрабы не додумаются написать кастом метод получения средней задержки)
 

Sargon

Известный
Проверенный
185
453
3. Буфер на прием был 576 байт, это ровно MTU самп. Но через релей к каждому пакету добавляется 10 байт заголовка socks5, поэтому большие пакеты от сервера обрезались и терялись. Сделал 586.

Код:
int maxDataSize = MTUSize - UDP_HEADER_SIZE

если бы работало, как ты описал, то у тебя бы каждый сплитнутый пакет тогда терялся
 

Софтик Инквизитор

Участник
Автор темы
19
92

Код:
int maxDataSize = MTUSize - UDP_HEADER_SIZE

если бы работало, как ты описал, то у тебя бы каждый сплитнутый пакет тогда терялся
бро, ты два разных числа спутал

maxDataSize = MTU-28 = 548 это порог, на котором одно сообщение пилится на сплиты. Это не размер датаграммы на проводе. Raknet пакует все в один UDP-сенд вплоть до полного MTU, то есть до 576.

Код:
0x40BA0C  push 0x240        ; recvfrom читает максимум в 576
0x40BA48  mov eax,[0x579448] ; структура прокси
0x40BA4D  cmp byte [eax+0x1a],0 ; работаем через прокси?
0x40BA73  sub esi,0xA       ; минус 10 байт socks5-хедера
0x40BA76  lea eax,[ebp-0xDEE] ; и сдвиг указателя на +10
0x40BA92  call 0x40AA30     ; отдали в raknet

То есть в буфере лежит [10 байт socks][датаграмма]. recvfrom в 576, из них 10 ест socks-хедер, на пейлоад остается 566. Все что сервер слал в 567-576 обрезалось еще в recvfrom, хвост терялся, пакет битый.

Буфер на отправку, кстати, тоже 576 (0x40C15A), а не 548. Вот тебе и ответ, рабочий размер = полный MTU.

Про "тогда каждый сплит бы терялся" - не каждый. Режется только то, что под самый MTU. Мелочь (большинство RPC, последний кусок сплита) сидит ниже 566 и доходит целой, поэтому коннект/спавн/чат работают

Пофикшено +10 (576 -> 586), ровно размер socks-хедера. Было бы дело в другом, именно эта цифра бы ничего не чинила. Твоя же ссылка это и подтверждает ))

Апдейт. По совету @AdCKuY_DpO4uLa убрал хардкод 1000мс. Теперь скрипт сам проверяет пинг до прокси по времени socks5-хендшейка и ставит интервал повтора как пинг+150+небольшой разброс. До первого замера остается 1000 по дефолту.
 
Последнее редактирование:
  • Нравится
Реакции: shidzu

Sargon

Известный
Проверенный
185
453
Это не размер датаграммы на проводе. Raknet пакует все в один UDP-сенд вплоть до полного MTU, то есть до 576.
закинул не то, GenerateDatagram:

и проверки при упаковке
[10 байт socks][датаграмма]
по итогу в датаграмме ты никогда не получишь 576, а следовательно буфер всегда был завышен и сокс5 хеадер туда спокойно влезает

покажи тогда хотя бы один пакет в вайршарке без прокси, который будет udp.length > 556:
548 maxDataBitSize (максимум, который ты в recvfrom получишь)
+ 8 байтов UDP заголовка
= 556
 
  • Нравится
Реакции: камущки

Софтик Инквизитор

Участник
Автор темы
19
92
закинул не то, GenerateDatagram:

и проверки при упаковке

по итогу в датаграмме ты никогда не получишь 576, а следовательно буфер всегда был завышен и сокс5 хеадер туда спокойно влезает

покажи тогда хотя бы один пакет в вайршарке без прокси, который будет udp.length > 556:
548 maxDataBitSize (максимум, который ты в recvfrom получишь)
+ 8 байтов UDP заголовка
= 556
не знал что датаграмма до MTU-28 режется, думал до полного 576
лишний "фикс" вырезал
спасибо за уточнение