Skip to content

feat: iSH support // captcha v2 // VLESS bonding // WRAP obfuscation - #162

Open
Moroka8 wants to merge 43 commits into
cacggghp:mainfrom
Moroka8:main
Open

feat: iSH support // captcha v2 // VLESS bonding // WRAP obfuscation#162
Moroka8 wants to merge 43 commits into
cacggghp:mainfrom
Moroka8:main

Conversation

@Moroka8

@Moroka8 Moroka8 commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Основная часть изменений связана с поддержкой iSH на iOS. Стандартный сетевой поллер Go использует epoll, который в iSH при регистрации нового соединения стабильно падает с EEXIST. Для обхода реализован ishListener под linux/386: принимает соединения через raw socketcall(SYS_ACCEPT), полностью минуя accept4 и epoll. Для самих соединений написан ishConn, который работает напрямую через syscall.Read/Write.

По капче: добавлен loggingTransport, который перехватывает тело запросов к captchaNotRobot.componentDone и captchaNotRobot.check, парсит из них device и browser_fp и сохраняет профиль на диск. При следующем автоматическом прохождении solveVkCaptcha подгружает этот профиль и подставляет его вместо сгенерированных данных, и в browser_fp/device, и в User-Agent. Попутно исправлено несколько мест, где запросы к VK API отправлялись с неверными заголовками: Origin был id.vk.ru вместо api.vk.ru, Referer некорректный, debug_info генерировался как динамический MD5 хэш, хотя реальный браузер шлёт статический SHA-256. RTT и downlink тоже приведены к реальным значениям (250ms, 1.45Mbps вместо 50ms и 9.5Mbps). Таймаут ручного режима поднят с 60 секунд до 3 минут.

По слайдер-капче: раньше для каждого кандидата рендерился отдельный image.RGBA, и только потом считались пиксели на стыках тайлов. Теперь пиксели читаются напрямую из исходного изображения через маппинг тайлов, без промежуточного рендера. Также добавлен requestSliderContentWithFallback: VK иногда возвращает show_type=checkbox в настройках, хотя реально отдаёт слайдер-контент, поэтому getContent пробуется с captcha_settings и без. Перед getContent теперь повторно вызывается componentDone, без этого VK отвечает ERROR, ожидая сигнал о загрузке виджета.

На стороне прокси добавлен /generic_proxy для ресурсов с чужих доменов (st.vk.com, api.vk.ru). Без него браузер блокировал их по CSP/CORS до того, как успевал отработать инъецируемый JS. Доставка токена обратно в прокси: sendBeacon → fetch → form POST как последний резерв, работает надёжнее.

KCP: интервал 20→10мс, окно 256→4096, MTU 1200→1280.

Close #139
Close #146
Close #149
Close #155
Close #164
Close #173

Moroka8 added 18 commits April 10, 2026 22:33
Optimized slider captcha solver to avoid CPU/RAM-heavy image rendering.
Added legacy TCP accept support specifically for iSH on linux/386 arch.
Fixed 'accept4: function not implemented' error in VLESS mode on iSH.
Fixed 'SIGSYS: bad system call (futex_time64)' by using blocking accept and avoiding Go's time.Sleep in spin-loops.
Fixed 'TCP accept error: file file+net ish-conn: file exists' by implementing custom ishConn that bypasses Go's network poller.
Fixed 'route ip+net: netlinkrib: invalid argument' by using directNet bypass in TURN client.
Fixed 'TCP accept error: bad file descriptor' by retaining os.File reference to prevent GC from closing the FD.
Configure global DNS resolver to use Yandex DNS by default.
Apply wrapISHListener to the manual captcha server to fix the missing syscall in iSH.
Implement navigator.sendBeacon for more reliable token delivery.
Add server-side success_token extraction in generic_proxy.
Make HTTP server shutdown non-fatal on iSH (ignores context deadline exceeded during cleanup)
Increase manual captcha timeout to 3 minutes using an independent context
Increase global DNS resolver timeout from 5s to 10s to improve stability
Added SavedProfile struct and persistence logic in vk_profile.json.
Implemented automatic interception of real browser telemetry (browser_fp, device JSON, headers) during manual captcha solves.
Integrated saved profile reuse in automated solve flows to bypass BOT status.
Restored dynamic MD5-based fingerprint generation as a fallback mechanism.
Reduce update interval to 10ms for lower latency
Increase window size to 4096 to improve bandwidth utilization
Bump MTU to 1280
@Moroka8

Moroka8 commented Apr 24, 2026

Copy link
Copy Markdown
Contributor Author

Протестировать pr можно здесь

@recrumptor

Copy link
Copy Markdown
Contributor

Протестировал на опенврт через ssh-туннель. Капча не завелась.

Нажмите здесь, чтобы развернуть текст Sat Apr 25 00:47:57 2026 daemon.info vk-client-arm64[29269]: ============================================== Sat Apr 25 00:47:57 2026 daemon.info vk-client-arm64[29269]: ACTION REQUIRED: MANUAL CAPTCHA SOLVING NEEDED Sat Apr 25 00:47:57 2026 daemon.info vk-client-arm64[29269]: If your browser didn't open automatically, Sat Apr 25 00:47:57 2026 daemon.info vk-client-arm64[29269]: manually open this URL: http://localhost:8765 Sat Apr 25 00:47:57 2026 daemon.info vk-client-arm64[29269]: ============================================== Sat Apr 25 00:47:57 2026 daemon.info vk-client-arm64[29269]: Sat Apr 25 00:47:57 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:47:57 [proxy HTTP server error] Opening browser... Sat Apr 25 00:48:03 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:48:03 [Captcha Proxy] HTTP GET / Sat Apr 25 00:48:03 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:48:03 [Captcha Proxy] HTTP GET /not_robot_captcha Sat Apr 25 00:48:11 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:48:11 [Captcha Proxy] HTTP GET / Sat Apr 25 00:48:11 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:48:11 [Captcha Proxy] HTTP GET /not_robot_captcha Sat Apr 25 00:48:21 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:48:21 [Captcha Proxy] Successfully intercepted and saved real browser profile! Sat Apr 25 00:49:31 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:49:31 [Captcha Proxy] HTTP GET /not_robot_captcha Sat Apr 25 00:49:31 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:49:31 [Captcha Proxy] Successfully intercepted and saved real browser profile! Sat Apr 25 00:49:35 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:49:35 http: proxy error: tls: first record does not look like a TLS handshake Sat Apr 25 00:49:42 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:49:42 http: proxy error: tls: first record does not look like a TLS handshake Sat Apr 25 00:49:51 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:49:51 http: proxy error: tls: first record does not look like a TLS handshake Sat Apr 25 00:50:57 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:50:57 [STREAM 1] [Captcha] manual captcha failed (attempt 3): manual captcha timed out after 3m Sat Apr 25 00:50:57 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:50:57 [STREAM 1] [FATAL] 0 connected streams and manual captcha failed/timed out. Sat Apr 25 00:50:57 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:50:57 [STREAM 1] [VK Auth] Failed with client_id=6287487: FATAL_CAPTCHA_FAILED_NO_STREAMS Sat Apr 25 00:50:57 2026 daemon.err vk-client-arm64[29269]: 2026/04/24 19:50:57 [STREAM 1] Fatal manual captcha error. Shutting down application.

@Moroka8

Moroka8 commented Apr 25, 2026

Copy link
Copy Markdown
Contributor Author

Протестировал на опенврт через ssh-туннель. Капча не завелась.

Попробуйте пройти капчу вручную на другом устройстве. В текущей версии профиль браузера при удачном прохождении сохраняется в файл vk_profile.json. Перенесите профиль с другого устройства и попробуйте проверить снова

Comment thread pkg/clientcore/manual_captcha.go
@yorkyx

yorkyx commented Apr 25, 2026

Copy link
Copy Markdown

У меня с капчей проблем нет, на последней версии все старутет. Но вопрос в другом, wireguard не хочет работать с iSH, запускаю тунель и ничего не грузит. На пк с тем же конфигом WG все работает. В чем может быть проблема?

Клиент запускаю вот так:
GOMAXPROCS=1 GODEBUG=asyncpreemptoff=1 ./client -listen 127.0.0.1:9000 -peer <VPS_IP>:56000 -vk-link https://vk.com/call/join/<CALL_ID>

Конфиг WG такой:

[Interface]
Address = 10.8.0.2
PrivateKey = <PRK>
MTU = 1280

[Peer]
PublicKey = <PBK>
AllowedIPs = 0.0.0.0/1, 128.0.0.0/4, 144.0.0.0/5, 152.0.0.0/7, 154.0.0.0/8, 155.0.0.0/9, 155.128.0.0/10, 155.192.0.0/12, 155.208.0.0/14, 155.212.0.0/17, 155.212.128.0/18, 155.212.208.0/20, 155.212.224.0/19, 155.213.0.0/16, 155.214.0.0/15, 155.216.0.0/13, 155.224.0.0/11, 156.0.0.0/6, 160.0.0.0/3, 192.0.0.0/2
Endpoint = 127.0.0.1:9000
PersistentKeepalive = 25

Cache all TURN addresses from VK and select them per stream.
Improve iSH socket handling with TCP options and full writes.
@Moroka8

Moroka8 commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

UPD:

Добавлена ротация TURN серверов. Теперь клиент не привязывается к одному адресу, а может использовать несколько TURN endpoints, которые возвращает VK.

Добавлен bonding для VLESS через -vless-bond. В этом режиме одно TCP-соединение можно распределять по нескольким активным smux/KCP-сессиям, что должно лучше использовать несколько TURN-соединений. Флаг нужно включать и на клиенте, и на сервере.

Добавлены настраиваемые KCP-профили через VK_TURN_KCP_PROFILE и переменные для ручной настройки KCP.

Добавлена дополнительная WRAP-обфускация DTLS-пакетов перед отправкой в TURN ChannelData. Включается флагом -wrap, ключ задаётся через -wrap-key, новый ключ можно сгенерировать через -gen-wrap-key. Клиент и сервер должны использовать одинаковый ключ. (Спасибо @anton48 за реализацию!)

Портирован новый VK captcha v2 solver. (Спасибо @WINGS-N за реализацию!)

Docker entrypoint теперь поддерживает VLESS_MODE, VLESS_BOND, WRAP_MODE и WRAP_KEY.

README переписан и структурирован заново

Протестировать pr можно здесь

@Moroka8
Moroka8 marked this pull request as ready for review May 7, 2026 19:39
@Moroka8 Moroka8 changed the title feat: iSH support // KCP optimization // Dynamic browser profiles feat: iSH support // captcha v2 // VLESS bonding // WRAP obfuscation May 7, 2026
@anton48

anton48 commented May 7, 2026

Copy link
Copy Markdown

Добавлена дополнительная WRAP-обфускация DTLS-пакетов перед отправкой в TURN ChannelData. Включается флагом -wrap, ключ задаётся через -wrap-key, новый ключ можно сгенерировать через -gen-wrap-key. Клиент и сервер должны использовать одинаковый ключ.

важный момент: если пытаться использовать эту функциональность, то надо запустить новый сервер с ключом и на другом порту по сравнению с тем, на котором работал старый сервер (старый сервер можно и не трогать для совместимости старых клиентов). новый порт нужен потому, что старая комбинация IP+port уже в списке на шейпинг у VK (я пока не нашел когда они убирают, может и никогда). к счастью, пока сам IP в список не попадает, только комбинация (по крайней мере, в моих тестах).

@Moroka8

Moroka8 commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

важный момент: если пытаться использовать эту функциональность, то надо запустить новый сервер с ключом и на другом порту по сравнению с тем, на котором работал старый сервер (старый сервер можно и не трогать для совместимости старых клиентов). новый порт нужен потому, что старая комбинация IP+port уже в списке на шейпинг у VK (я пока не нашел когда они убирают, может и никогда). к счастью, пока сам IP в список не попадает, только комбинация (по крайней мере, в моих тестах).

Странно. У меня лично скорость передачи трафика увеличилась после пересоздания контейнера, не меняя при этом на нем порты. Нужен фидбэк от еще нескольких людей, чтобы понять, у кого из нас случай является исключением

@anton48

anton48 commented May 7, 2026

Copy link
Copy Markdown

важный момент: если пытаться использовать эту функциональность, то надо запустить новый сервер с ключом и на другом порту по сравнению с тем, на котором работал старый сервер (старый сервер можно и не трогать для совместимости старых клиентов). новый порт нужен потому, что старая комбинация IP+port уже в списке на шейпинг у VK (я пока не нашел когда они убирают, может и никогда). к счастью, пока сам IP в список не попадает, только комбинация (по крайней мере, в моих тестах).

Странно. У меня лично скорость передачи трафика увеличилась после пересоздания контейнера, не меняя при этом на нем порты. Нужен фидбэк от еще нескольких людей, чтобы понять, у кого из нас случай является исключением

в моих тестах было четко: стоит один раз подключиться на оригинальном клиенте по IP+port и эта связка улетает в шейпинг. перед этим тестирую своей утилитой скорость - все ок, подключился - шейпинг. тестирую другой порт - ок, подключился - шейпинг.

видел у вас новую интересную функциональность ротации TURN серверов, может быть то, что у вас сработало является ее следствием (другой TURN сервер не знает еще про эту связку IP+port)?

@Moroka8

Moroka8 commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

видел у вас новую интересную функциональность ротации TURN серверов, может быть то, что у вас сработало является ее следствием (другой TURN сервер не знает еще про эту связку IP+port)?

Сомнительно, ибо было бы странно запоминать IP и порт только в первом выделенном TURN сервере. В дальнейшем, если появится надобность, можно будет проверить эту гипотезу

@anton48

anton48 commented May 8, 2026

Copy link
Copy Markdown

Сомнительно, ибо было бы странно запоминать IP и порт только в первом выделенном TURN сервере.

на мой взгляд это как раз понятное дешевое решение в лоб :) конкретную комбинацию IP+port видит конкретный TURN сервер (если там нет отдельной сущности DPI над ними). дальше он может это использовать у себя, а может распространять информацию, что сложнее.

я, кстати, вспомнил, что есть как минимум одно внешнее подтверждение моей гипотезы про ip+port: anton48/vk-turn-proxy-ios#5 (comment)

DaRk1c3 сначала поставил сервер с моим патчем WRAP, не получил скорости, я ему описал технологию по замене порта и тогда у него все быстро заработало.

@RealSerga

Copy link
Copy Markdown

Заметил один вероятный баг, первый поток запускается с streamID=1, а потом цикл дополнительных потоков тоже начинается с i := 1, то есть при -n > 1 stream, 1 создаётся дважды, а stream 0 не создаётся вообще, ибо потом там в цикле тоже for i := 1
Так надо?

WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request May 20, 2026
Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit dbfadf1)
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request May 20, 2026
Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit 272aa36)
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request May 20, 2026
Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit 75edb06)
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request May 20, 2026
…apath

Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit 0f24441; cipher selection extended to aes-ctr/chacha20-xor)
samosvalishe and others added 7 commits May 22, 2026 17:09
Port SRTP-like AEAD wrap from samosvalishe/vk-turn-proxy 0.11.0 and adapt it to the current client relay paths.

Co-authored-by: samosvalishe <samosvalishe@users.noreply.github.com>
Move the client implementation into pkg/clientcore so mobile wrappers can call Run(ctx, Config) directly while the CLI remains a thin wrapper.

Adapted from ios-clientcore-refactor on top of the current wrap implementation.
Use packet info on Linux to remember the local destination IP for each client and send DTLS replies from that same address.

Refs #3
Expose manual captcha on a configured host:port for router and OpenWrt setups.

Refs cacggghp#157
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request Aug 29, 2026
Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit dbfadf1)
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request Aug 29, 2026
Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit 272aa36)
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request Aug 29, 2026
Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit 75edb06)
WINGS-N pushed a commit to WINGS-N/vk-turn-proxy that referenced this pull request Aug 29, 2026
…apath

Co-authored-by: Moroka8 <moroka8@mail.ru>
(ported from cacggghp/vk-turn-proxy PR cacggghp#162, commit 0f24441; cipher selection extended to aes-ctr/chacha20-xor)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants