From e1a5a3f7ac8ea3c4a4a68a9212133ae5be7403bf Mon Sep 17 00:00:00 2001 From: cacggghp Date: Tue, 14 Apr 2026 21:17:32 +0000 Subject: [PATCH 1/3] fix: print TURN IP to stdout for routes.sh --- client/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/main.go b/client/main.go index 21e81a4..71a8625 100644 --- a/client/main.go +++ b/client/main.go @@ -1559,6 +1559,7 @@ func oneTurnConnection(ctx context.Context, turnParams *turnParams, peer *net.UD return } turnServerAddr = turnServerUDPAddr.String() + fmt.Println(turnServerUDPAddr.IP) var cfg *turn.ClientConfig var turnConn net.PacketConn var d net.Dialer @@ -2162,6 +2163,7 @@ func createSmuxSession(ctx context.Context, tp *turnParams, peer *net.UDPAddr, i return nil, nil, fmt.Errorf("resolve TURN addr: %w", err) } turnServerAddr = turnServerUDPAddr.String() + fmt.Println(turnServerUDPAddr.IP) // 2. Connect to TURN server var turnConn net.PacketConn From 597311ff12cbb5c2e9e3dcfba0db32dc398fa949 Mon Sep 17 00:00:00 2001 From: cacggghp Date: Tue, 14 Apr 2026 22:05:45 +0000 Subject: [PATCH 2/3] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf0a746..468f45f 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,13 @@ - https://github.com/NedgNDG/vk-proxy-auto-installer - автоустановщик VK TURN Proxy (TUI) #### Android +##### Мои любимые +- https://github.com/samosvalishe/turn-proxy-android - клиент для андроида c Material 3 UI и автоапдейтами (Kotlin) - https://github.com/MYSOREZ/vk-turn-proxy-android - клиент для андроида -- https://github.com/WINGS-N/WINGSV - клиент для андроида с One UI, WireGuard, раздачей VPN с root - https://github.com/kiper292/wireguard-turn-android - клиент для андроида интегрированный в WireGuard +##### Ещё +- https://github.com/WINGS-N/WINGSV - клиент для андроида с One UI, WireGuard, раздачей VPN с root - https://github.com/oxsidee/vkpn - клиент для андроида (кроссплатформенный Flutter) -- https://github.com/antongospod/turn-proxy-android - клиент для андроида c Material 3 UI и автоапдейтами (Kotlin) - https://github.com/amurcanov/proxy-turn-vk-android - клиент для андроида с WireGuard #### iOS From ae15a400e87fc2dafeaa57d7d2b0d04f66661b1b Mon Sep 17 00:00:00 2001 From: Moroka8 Date: Thu, 16 Apr 2026 02:18:06 +0700 Subject: [PATCH 3/3] fix: handle checkbox captcha and improve manual proxy debug --- client/main.go | 2 +- client/manual_captcha.go | 20 ++++++++++++++++---- client/slider_captcha.go | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/client/main.go b/client/main.go index 71a8625..73dfd17 100644 --- a/client/main.go +++ b/client/main.go @@ -228,7 +228,7 @@ func applyBrowserProfileFhttp(req *fhttp.Request, profile Profile) { } func generateBrowserFp(profile Profile) string { - data := profile.UserAgent + profile.SecChUa + "1920x1080x24" + data := profile.UserAgent + profile.SecChUa + "1920x1080x24" + strconv.FormatInt(time.Now().UnixNano(), 10) h := md5.Sum([]byte(data)) return hex.EncodeToString(h[:]) } diff --git a/client/manual_captcha.go b/client/manual_captcha.go index 27f958d..826478c 100644 --- a/client/manual_captcha.go +++ b/client/manual_captcha.go @@ -125,6 +125,7 @@ func rewriteProxyRequest(req *http.Request, targetURL *neturl.URL) { req.Host = targetURL.Host req.Header.Del("Accept-Encoding") + req.Header.Del("TE") // Disable transfer encoding compression for _, headerName := range []string{"Origin", "Referer"} { if rewritten := rewriteProxyHeaderURL(req.Header.Get(headerName), targetURL); rewritten != "" { req.Header.Set(headerName, rewritten) @@ -341,7 +342,7 @@ func newCaptchaProxyTransport(dialer *dnsdialer.Dialer) *http.Transport { IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, - ForceAttemptHTTP2: true, + ForceAttemptHTTP2: false, } if dialer != nil { transport.DialContext = dialer.DialContext @@ -458,16 +459,17 @@ func solveCaptchaViaProxy(redirectURI string, dialer *dnsdialer.Dialer) (string, rewriteProxyRequest(req.Out, targetURL) }, ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { - log.Printf("captcha proxy error for %s: %v", r.URL.String(), err) + log.Printf("[Captcha Proxy] ERROR for %s %s: %v", r.Method, r.URL.String(), err) w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusBadGateway) - _, _ = fmt.Fprintf(w, `

Captcha proxy error

%v

`, err) + _, _ = fmt.Fprintf(w, `

Captcha proxy error

%s %s

%v

`, r.Method, r.URL.String(), err) }, ModifyResponse: func(res *http.Response) error { rewriteProxyCookies(res.Header) if res.StatusCode >= 300 && res.StatusCode < 400 { if loc := res.Header.Get("Location"); loc != "" { + log.Printf("[Captcha Proxy] Redirecting to: %s", loc) if rewritten, ok := rewriteProxyRedirectLocation(loc, targetURL); ok { res.Header.Set("Location", rewritten) } else { @@ -477,7 +479,13 @@ func solveCaptchaViaProxy(redirectURI string, dialer *dnsdialer.Dialer) (string, } contentType := res.Header.Get("Content-Type") - shouldInspectBody := strings.Contains(contentType, "text/html") || strings.Contains(res.Request.URL.Path, "captchaNotRobot.check") + contentEncoding := res.Header.Get("Content-Encoding") + log.Printf("[Captcha Proxy] %s %d | Content-Type: %q, Encoding: %q", res.Request.Method, res.StatusCode, contentType, contentEncoding) + + shouldInspectBody := strings.Contains(contentType, "text/html") || + strings.Contains(contentType, "application/xhtml+xml") || + strings.Contains(res.Request.URL.Path, "captchaNotRobot.check") + if !shouldInspectBody { return nil } @@ -517,6 +525,8 @@ func solveCaptchaViaProxy(redirectURI string, dialer *dnsdialer.Dialer) (string, "Cross-Origin-Embedder-Policy", "Cross-Origin-Resource-Policy", "X-Frame-Options", + "Strict-Transport-Security", + "Alt-Svc", } { res.Header.Del(headerName) } @@ -559,7 +569,9 @@ func solveCaptchaViaProxy(redirectURI string, dialer *dnsdialer.Dialer) (string, }) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + log.Printf("[Captcha Proxy] HTTP %s %s", r.Method, r.URL.String()) if r.URL.Path == "/" && targetURL.Path != "" && targetURL.Path != "/" && r.URL.RawQuery == "" { + log.Printf("[Captcha Proxy] Redirecting ROOT to: %s", localCaptchaURLForTarget(targetURL)) http.Redirect(w, r, localCaptchaURLForTarget(targetURL), http.StatusTemporaryRedirect) return } diff --git a/client/slider_captcha.go b/client/slider_captcha.go index 166a6ab..b4644c4 100644 --- a/client/slider_captcha.go +++ b/client/slider_captcha.go @@ -153,7 +153,7 @@ func (s *captchaNotRobotSession) requestComponentDone() error { } func (s *captchaNotRobotSession) requestCheckboxCheck() (*captchaCheckResult, error) { - return s.requestCheck("[]", base64.StdEncoding.EncodeToString([]byte("{}"))) + return s.requestCheck(generateSliderCursor(0, 1), base64.StdEncoding.EncodeToString([]byte("{}"))) } func (s *captchaNotRobotSession) requestSliderContent(sliderSettings string) (*sliderCaptchaContent, error) { @@ -267,6 +267,22 @@ func callCaptchaNotRobotWithSliderPOC( sliderContent, err := session.requestSliderContent(sliderSettings) if err != nil { + log.Printf( + "[STREAM %d] [Captcha] Slider getContent failed (status: %v). Trying to solve as a checkbox instead...", + streamID, + err, + ) + // Fallback: maybe it's just a checkbox that needs a human-like check + time.Sleep(300 * time.Millisecond) + finalCheck, err2 := session.requestCheckboxCheck() + if err2 == nil && finalCheck.Status == "OK" { + if finalCheck.SuccessToken == "" { + return "", fmt.Errorf("success_token not found in fallback check") + } + log.Printf("[STREAM %d] [Captcha] Fallback checkbox check succeeded!", streamID) + session.requestEndSession() + return finalCheck.SuccessToken, nil + } return "", fmt.Errorf("check status: %s (slider getContent failed: %w)", initialCheck.Status, err) }