Перейти до вмісту
Guides 8 хв читання 974 переглядів

Використання проксі в Go (Golang)

Ознайомтеся з основами використання HTTP та SOCKS проксі в Go (Golang). Ц

Використання проксі в Go (Golang)

Використання проксі в Go передбачає налаштування http.Transport для http.Client за допомогою функції Proxy, зазвичай http.ProxyURL для статичних проксі або спеціальної функції для динамічного вибору проксі.

Навіщо використовувати проксі в Go?

Проксі слугують різним цілям у мережевій комунікації, особливо при виконанні HTTP-запитів з Go-додатків:

  • Анонімність: Маскування оригінальної IP-адреси клієнта.
  • Геотаргетинг: Доступ до контенту або послуг, обмежених певними географічними регіонами, шляхом маршрутизації запитів через проксі, розташовані в цих регіонах.
  • Обмеження швидкості запитів: Розподіл запитів між кількома IP-адресами, щоб уникнути перевищення лімітів швидкості, встановлених цільовими серверами.
  • Веб-скрейпінг: Сприяння великомасштабному збору даних шляхом ротації IP-адрес, обходу виявлення та керування обсягом запитів.
  • Безпека та фільтрація: Маршрутизація трафіку через корпоративні проксі для сканування безпеки, фільтрації контенту або контролю доступу.
  • Налагодження: Перехоплення та інспектування трафіку.

Налаштування HTTP-клієнта з проксі

Стандартна бібліотека Go net/http надає надійну підтримку конфігурацій проксі. Основний механізм передбачає зміну http.Transport, пов'язаного з http.Client.

Використання http.ProxyFromEnvironment

Найпростіший спосіб використання проксі — це використання змінних середовища. Функція Go http.ProxyFromEnvironment перевіряє змінні середовища HTTP_PROXY, HTTPS_PROXY та NO_PROXY.

  • HTTP_PROXY: Використовується для http:// запитів.
  • HTTPS_PROXY: Використовується для https:// запитів.
  • NO_PROXY: Список хостів, розділених комами, які повинні обходити проксі.
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func main() {
    // Встановлення змінних середовища (для демонстрації)
    os.Setenv("HTTP_PROXY", "http://your_proxy_ip:port")
    os.Setenv("HTTPS_PROXY", "http://your_proxy_ip:port") // Примітка: HTTPS_PROXY може бути HTTP-проксі
    // os.Setenv("NO_PROXY", "localhost,127.0.0.1")

    client := &http.Client{
        Transport: &http.Transport{
            Proxy: http.ProxyFromEnvironment,
        },
        Timeout: 10 * time.Second,
    }

    resp, err := client.Get("http://httpbin.org/ip")
    if err != nil {
        fmt.Printf("Помилка при виконанні запиту: %v\n", err)
        return
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Помилка при читанні тіла відповіді: %v\n", err)
        return
    }
    fmt.Printf("Відповідь від httpbin.org/ip:\n%s\n", body)

    os.Unsetenv("HTTP_PROXY")
    os.Unsetenv("HTTPS_PROXY")
}

Використання http.ProxyURL для статичних проксі

Для явної конфігурації проксі використовується http.ProxyURL. Ця функція приймає *url.URL, що представляє адресу проксі.

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "time"
)

func main() {
    proxyStr := "http://your_proxy_ip:port" // Замініть на адресу вашого проксі
    proxyURL, err := url.Parse(proxyStr)
    if err != nil {
        fmt.Printf("Помилка при парсингу URL проксі: %v\n", err)
        return
    }

    client := &http.Client{
        Transport: &http.Transport{
            Proxy: http.ProxyURL(proxyURL),
        },
        Timeout: 10 * time.Second,
    }

    resp, err := client.Get("http://httpbin.org/ip")
    if err != nil {
        fmt.Printf("Помилка при виконанні запиту: %v\n", err)
        return
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Помилка при читанні тіла відповіді: %v\n", err)
        return
    }
    fmt.Printf("Відповідь від httpbin.org/ip:\n%s\n", body)
}

Автентифікація проксі

Багато проксі вимагають автентифікації. Для HTTP/HTTPS проксі, що використовують базову автентифікацію, облікові дані можуть бути вбудовані безпосередньо в URL проксі:

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "time"
)

func main() {
    // Формат: "http://username:password@proxy_ip:port"
    proxyStr := "http://user:password@your_auth_proxy_ip:port" // Замініть на ваш автентифікований проксі
    proxyURL, err := url.Parse(proxyStr)
    if err != nil {
        fmt.Printf("Помилка при парсингу URL проксі: %v\n", err)
        return
    }

    client := &http.Client{
        Transport: &http.Transport{
            Proxy: http.ProxyURL(proxyURL),
        },
        Timeout: 10 * time.Second,
    }

    resp, err := client.Get("http://httpbin.org/ip")
    if err != nil {
        fmt.Printf("Помилка при виконанні запиту з автентифікованим проксі: %v\n", err)
        return
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Помилка при читанні тіла відповіді: %v\n", err)
        return
    }
    fmt.Printf("Відповідь від httpbin.org/ip через автентифікований проксі:\n%s\n", body)
}

Використання SOCKS5 проксі

Хоча net/http безпосередньо підтримує HTTP/HTTPS проксі, SOCKS5 проксі вимагають додаткового пакету: golang.org/x/net/proxy. SOCKS5 працює на нижчому рівні, ніж HTTP проксі, підтримуючи різні протоколи.

Щоб використовувати SOCKS5 проксі, вам потрібно створити Dialer за допомогою пакету proxy, а потім призначити його полю DialContext у http.Transport.

package main

import (
    "context"
    "fmt"
    "io"
    "net"
    "net/http"
    "time"

    "golang.org/x/net/proxy" // Переконайтеся, що ви виконали 'go get golang.org/x/net/proxy'
)

func main() {
    socks5Proxy := "socks5://user:password@your_socks5_proxy_ip:port" // Замініть на ваш SOCKS5 проксі

    dialer, err := proxy.SOCKS5("tcp", socks5Proxy[len("socks5://"):], nil, proxy.Direct) // Базова автентифікація обробляється dialer'ом
    if err != nil {
        fmt.Printf("Помилка при створенні SOCKS5 dialer: %v\n", err)
        return
    }

    // Для автентифікованого SOCKS5, функція proxy.SOCKS5 обробляє його, якщо URL містить облікові дані.
    // Якщо функція proxy.SOCKS5 не парсить облікові дані безпосередньо, вам може знадобитися
    // витягти їх і передати структуру proxy.Auth. Приклад:
    // auth := &proxy.Auth{User: "user", Password: "password"}
    // dialer, err := proxy.SOCKS5("tcp", "your_socks5_proxy_ip:port", auth, proxy.Direct)

    client := &http.Client{
        Transport: &http.Transport{
            DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
                return dialer.Dial(network, addr)
            },
            // За бажанням, встановіть TLSClientConfig для HTTPS через SOCKS5
            // TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // Використовуйте з обережністю
        },
        Timeout: 10 * time.Second,
    }

    resp, err := client.Get("http://httpbin.org/ip")
    if err != nil {
        fmt.Printf("Помилка при виконанні запиту з SOCKS5 проксі: %v\n", err)
        return
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Помилка при читанні тіла відповіді: %v\n", err)
        return
    }
    fmt.Printf("Відповідь від httpbin.org/ip через SOCKS5 проксі:\n%s\n", body)
}

Динамічний вибір та ротація проксі

Для таких додатків, як веб-скрейпінг або великомасштабний збір даних, ротація проксі є важливою для уникнення блокування IP-адрес та керування обсягом запитів. Це вимагає спеціальної функції Proxy для http.Transport.

Поле Proxy у http.Transport очікує функцію з сигнатурою func(*http.Request) (*url.URL, error). Ця функція викликається перед кожним запитом, дозволяючи динамічний вибір проксі на основі властивостей запиту або стратегії ротації.

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "sync"
    "time"
)

// ProxyRotator керує списком проксі та забезпечує циклічний вибір.
type ProxyRotator struct {
    proxies []*url.URL
    current int
    mu      sync.Mutex
}

// NewProxyRotator створює новий ProxyRotator зі зрізу URL-адрес проксі.
func NewProxyRotator(proxyStrings []string) (*ProxyRotator, error) {
    proxies := make([]*url.URL, len(proxyStrings))
    for i, s := range proxyStrings {
        u, err := url.Parse(s)
        if err != nil {
            return nil, fmt.Errorf("недійсний URL проксі '%s': %w", s, err)
        }
        proxies[i] = u
    }
    return &ProxyRotator{
        proxies: proxies,
        current: 0,
    }, nil
}

// GetProxy повертає наступний проксі в циклічному порядку.
func (pr *ProxyRotator) GetProxy(_ *http.Request) (*url.URL, error) {
    if len(pr.proxies) == 0 {
        return nil, nil // Без проксі
    }

    pr.mu.Lock()
    defer pr.mu.Unlock()

    proxy := pr.proxies[pr.current]
    pr.current = (pr.current + 1) % len(pr.proxies)
    return proxy, nil
}

func main() {
    proxyList := []string{
        "http://user1:[email protected]:8080",
        "http://user2:[email protected]:8080",
        "http://user3:[email protected]:8080",
    }

    rotator, err := NewProxyRotator(proxyList)
    if err != nil {
        fmt.Printf("Помилка при створенні ротатора проксі: %v\n", err)
        return
    }

    client := &http.Client{
        Transport: &http.Transport{
            Proxy: rotator.GetProxy, // Призначити метод GetProxy ротатора
        },
        Timeout: 15 * time.Second,
    }

    for i := 0; i < 5; i++ {
        resp, err := client.Get("http://httpbin.org/ip")
        if err != nil {
            fmt.Printf("Помилка запиту %d: %v\n", i+1, err)
            continue
        }
        defer resp.Body.Close()

        body, err := io.ReadAll(resp.Body)
        if err != nil {
            fmt.Printf("Помилка читання тіла запиту %d: %v\n", i+1, err)
            continue
        }
        fmt.Printf("IP запиту %d: %s\n", i+1, body)
        time.Sleep(1 * time.Second) // Імітація деякої роботи
    }
}

Цей приклад реалізує базовий циклічний ротатор. Більш просунуті ротатори можуть:
* Відстежувати стан проксі та видаляти несправні проксі.
* Реалізовувати різні стратегії ротації (наприклад, зважені, випадкові).
* Інтегруватися із зовнішніми службами керування проксі.

HTTPS-трафік через проксі

Коли http.Client виконує https:// запит через HTTP-проксі, http.Transport виконує рукостискання методом CONNECT з проксі. Клієнт просить проксі встановити TCP-тунель до цільового хоста та порту (зазвичай 443). Після встановлення тунелю клієнт виконує TLS-рукостискання безпосередньо з цільовим сервером через проксі-тунель. Сам проксі не розшифровує HTTPS-трафік (якщо це не проксі "людина посередині", що є іншим сценарієм, що вимагає спеціальних конфігурацій довіри).

Для https:// запитів функція Proxy повинна повертати URL проксі як зазвичай. net/http Go автоматично обробляє метод CONNECT.

Перевірка TLS/SSL

За замовчуванням клієнти Go виконують строгу перевірку TLS-сертифікатів. Якщо сертифікат цільового сервера не може бути перевірений (наприклад, самопідписаний, прострочений або неперевірений CA), запит завершиться помилкою.

У певних сценаріях (наприклад, тестування з відомими самопідписаними сертифікатами в контрольованому середовищі) ви можете вимкнути перевірку сертифікатів за допомогою InsecureSkipVerify у tls.Config.

package main

import (
    "crypto/tls"
    "fmt"
    "io"
    "net"
    "net/http"
    "net/url"
    "time"
)

func main() {
    proxyStr := "http://your_proxy_ip:port"
    proxyURL, err := url.Parse(proxyStr)
    if err != nil {
        fmt.Printf("Помилка при парсингу URL проксі: %v\n", err)
        return
    }

    // Налаштування спеціального Transport для параметрів TLS
    tr := &http.Transport{
        Proxy: http.ProxyURL(proxyURL),
        TLSClientConfig: &tls.Config{
            // ПОПЕРЕДЖЕННЯ: InsecureSkipVerify не слід використовувати в виробничих середовищах.
            // Він вимикає перевірку ланцюжка сертифікатів та імені хоста.
            InsecureSkipVerify: true,
        },
        DialContext: (&net.Dialer{
            Timeout:   30 * time.Second,
            KeepAlive: 30 * time.Second,
        }).DialContext,
        MaxIdleConns:        100,
        IdleConnTimeout:     90 * time.Second,
        TLSHandshakeTimeout: 10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    }

    client := &http.Client{
        Transport: tr,
        Timeout: 15 * time.Second, // Загальний тайм-аут запиту
    }

    // Приклад цілі для HTTPS
    resp, err := client.Get("https://example.com")
    if err != nil {
        fmt.Printf("Помилка при виконанні HTTPS-запиту з проксі: %v\n", err)
        return
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Помилка при читанні тіла відповіді: %v\n", err)
        return
    }
    fmt.Printf("Статус відповіді від https://example.com: %s\n", resp.Status)
    // fmt.Printf("Тіло відповіді: %s\n", body) // Опущено для стислості
    _ = body
}

Порівняння: HTTP/HTTPS проти SOCKS5 проксі

Функція HTTP/HTTPS Проксі SOCKS5 Проксі
Рівень протоколу Прикладний рівень (Рівень 7) Сесійний рівень (Рівень 5)
Підтримуваний трафік Переважно HTTP/HTTPS запити Будь-який TCP/UDP трафік (HTTP, FTP, SMTP, DNS тощо)
Фільтрація трафіку Може перевіряти HTTP-заголовки, URL-адреси та вміст Зазвичай не перевіряє вміст трафіку
Автентифікація HTTP Basic, Digest (Go підтримує лише Basic в URL) Ім'я користувача/Пароль (метод SOCKS5 AUTH)
Простота використання (Go) Вбудована підтримка в net/http (http.ProxyURL) Вимагає пакету golang.org/x/net/proxy
Продуктивність Потенційно вищі накладні витрати через парсинг HTTP Зазвичай нижчі накладні витрати, діє як простий ретранслятор
Випадки використання Веб-скрейпінг, взаємодія з API, веб-фільтрація Загальне тунелювання мережі, обхід брандмауерів

Найкращі практики

  • Встановлюйте тайм-аути: Завжди налаштовуйте тайм-аути для http.Client та http.Transport (наприклад, DialContext, TLSHandshakeTimeout), щоб запобігти зависанню запитів на невизначений термін, особливо при роботі з ненадійними проксі.
  • Надійна обробка помилок: Помилки, пов'язані з проксі, можуть відрізнятися (наприклад, net.OpError для проблем з підключенням, io.EOF для несподіваних відключень). Реалізуйте комплексну обробку помилок та логіку повторних спроб.
  • Керування проксі: Для динамічних сценаріїв реалізуйте надійну систему керування проксі, яка відстежує стан проксі, ефективно ротує проксі та витончено обробляє збої.
  • Керування ресурсами: Переконайтеся, що resp.Body.Close() викликається за допомогою defer для звільнення мережевих ресурсів.
  • Контекст для скасування: Використовуйте context.Context з http.Request, щоб увімкнути скасування запитів та керування тайм-аутами між функціями.
  • Уникайте InsecureSkipVerify: Не використовуйте InsecureSkipVerify = true у виробничих середовищах, якщо ви повністю не розумієте наслідків для безпеки та не маєте компенсуючих засобів контролю.
Оновлено: 03.03.2026
Назад до категорії

Читайте також

Guides 2 хв

Проксі для Nike SNKRS: купуйте лімітовані релізи та створюйте безліч акаунтів

Використовуйте residential або mobile проксі для Nike SNKRS, щоб брати участь у розіграшах з кількох акаунтів, обходити IP-ліміти та купувати лімітовані дропи без банів. Який тип обрати та як налаштувати GProxy.

Guides 2 хв

Як налаштувати проксі на iPhone (Wi-Fi та SOCKS5)

Налаштуйте проксі на iPhone через стандартні параметри Wi-Fi (HTTP/HTTPS) або додаток для проксі, як-от Shadowrocket, для SOCKS5 та стільникового зв'язку. Покрокове налаштування iOS та обмеження, про які варто знати.

Guides 3 хв

Проксі для Tinder: мультиакаунтинг та уникнення банів

Використовуйте мобільні або резидентські проксі для Tinder, щоб керувати кількома профілями та уникати IP shadowbans. Чому мобільні виграють, як усе налаштувати та чому сам по собі проксі не змінить ваше місто.

Guides 2 хв

Проксі для StockX: моніторинг цін та керування акаунтами

Використовуйте residential, ISP або mobile проксі для StockX, щоб моніторити ціни, керувати кількома акаунтами та купувати дропи без банів. Ось який тип обрати та як налаштувати GProxy.

Guides 3 хв

Проксі для OpenAI API: доступ, ліміти (Rate Limits) та налаштування

Маршрутизуйте OpenAI API через residential або ISP проксі, щоб отримати доступ до підтримуваних регіонів, уникнути 429 rate limits та ізолювати акаунти. Який проксі використовувати плюс приклади налаштування Python.

Guides 1 хв

Налаштування проксі в Cypress для E2E тестування

Налаштування проксі в Cypress: змінні HTTP_PROXY, cy-proxy-middleware та тестування геозалежного контенту.

Спробуйте наші проксі

20,000+ проксі в 100+ країнах світу

support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.