From cd9389e9fd78a123518a489dc10c48fd177357b3 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Fri, 20 Mar 2026 18:54:10 +0700 Subject: [PATCH] Implement SOCKS5 and HTTP proxy support in main.go, enhancing outgoing request handling. Update README.md to document new proxy environment variables. Update go.mod to include golang.org/x/net dependency. --- README.md | 1 + go.mod | 2 ++ main.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f971d70..15aa78c 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ - `TELEMT_LINK_HOST` - хост для генерации `tg://proxy` ссылок, если API их не вернуло. - `TELEMT_LINK_PORT` - порт для ссылок (по умолчанию `9443`). - `TELEMT_TLS_DOMAIN` - TLS-домен для генерации `EE-TLS` ссылки (опционально). +- `ALL_PROXY`, `HTTPS_PROXY`, `HTTP_PROXY` - прокси для исходящих запросов (Telegram API, Telemt API). Поддерживаются `socks5://`, `socks5h://`, `http://`, `https://`. Приоритет: ALL_PROXY → HTTPS_PROXY → HTTP_PROXY. ## Быстрый старт (локально, Linux/bash) diff --git a/go.mod b/go.mod index 47dda09..066560c 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module telemt-bot go 1.22 + +require golang.org/x/net v0.28.0 diff --git a/main.go b/main.go index 675d464..b84816c 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "log" + "net" "net/http" "net/url" "os" @@ -17,6 +18,8 @@ import ( "strings" "syscall" "time" + + "golang.org/x/net/proxy" ) const ( @@ -111,22 +114,73 @@ type createUserResponse struct { Secret string `json:"secret"` } +func makeHTTPTransport() (*http.Transport, error) { + tr := &http.Transport{ + MaxIdleConns: 64, + MaxIdleConnsPerHost: 32, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 5 * time.Second, + ForceAttemptHTTP2: true, + DisableCompression: false, + } + + proxyURL := getProxyURL() + if proxyURL == "" { + return tr, nil + } + + u, err := url.Parse(proxyURL) + if err != nil { + return nil, fmt.Errorf("invalid proxy URL %q: %w", proxyURL, err) + } + + switch u.Scheme { + case "socks5", "socks5h": + dialer, err := proxy.FromURL(u, proxy.Direct) + if err != nil { + return nil, fmt.Errorf("socks5 proxy %q: %w", proxyURL, err) + } + if ctxDialer, ok := dialer.(proxy.ContextDialer); ok { + tr.DialContext = ctxDialer.DialContext + } else { + tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { + return dialer.Dial(network, addr) + } + } + log.Printf("using SOCKS5 proxy: %s", u.Host) + case "http", "https": + tr.Proxy = http.ProxyURL(u) + log.Printf("using HTTP proxy: %s", u.Host) + default: + return nil, fmt.Errorf("unsupported proxy scheme %q (use socks5, socks5h, http, or https)", u.Scheme) + } + + return tr, nil +} + +func getProxyURL() string { + for _, key := range []string{"ALL_PROXY", "all_proxy", "HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"} { + if v := strings.TrimSpace(os.Getenv(key)); v != "" { + return v + } + } + return "" +} + func main() { cfg, err := loadConfig() if err != nil { log.Fatalf("config error: %v", err) } + transport, err := makeHTTPTransport() + if err != nil { + log.Fatalf("transport error: %v", err) + } + httpClient := &http.Client{ - Transport: &http.Transport{ - MaxIdleConns: 64, - MaxIdleConnsPerHost: 32, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 5 * time.Second, - ForceAttemptHTTP2: true, - DisableCompression: false, - }, - Timeout: cfg.TelegramTimeout, + Transport: transport, + Timeout: cfg.TelegramTimeout, } b := &bot{