GeekProxy в Go, PHP, Java и C#

Четыре языка, четыре стандартных HTTP-клиента, один прокси. Каждый раздел ниже самодостаточен: точные имена опций из официальной документации, сниппет, который тянет ipinfo через прокси, и одна ловушка, своя у каждой платформы. У Java ловушка самая противная, так что кусок про Basic поверх CONNECT не пропускайте.

Что нужно: активный план GeekProxy и данные прокси из кабинета. Каждый сниппет запускается меньше чем за минуту, если тулчейн уже стоит.

Получить прокси

1 Перед началом

Под капотом все четыре клиента делают одно и то же. Для цели на https:// они открывают CONNECT-туннель через прокси и шлют Proxy-Authorization только в этом CONNECT. Сайт видит IP прокси, остальное на вашей машине не меняется.

  • HTTP-прокси с логином и паролем это безопасный выбор в любом из четырёх языков. SOCKS5 с паролем тоже работает во всех четырёх, оговорки в каждом разделе
  • Порты GeekProxy это обычные HTTP-прокси. Там, где клиент спрашивает схему самого прокси, это http, даже для целей на https://
  • На плане с белым списком IP данные доступа убираем: никакого LOGIN:PASSWORD@ в URL, никакого аутентификатора, никакого объекта с учётными данными
  • Спецсимволы в пароле внутри URL кодируются процентами. Опции, которые берут логин и пароль отдельными строками, хотят их как есть

Что понадобится

  • Активный план GeekProxy (датацентр, ISP или резидентские)
  • Данные прокси из кабинета: хост, порт, логин, пароль
  • Go с net/http, PHP 7.3 или новее с расширением curl, JDK 11 или новее, .NET 6 или новее
Ваши данные доступа
  • Поле Откуда взять
  • Протокол HTTP / SOCKS5
  • Хост IP или имя шлюза из кабинета
  • Порт из кабинета
  • Логин из кабинета
  • Пароль из кабинета

2 Где взять данные прокси

  1. Войдите в кабинет GeekProxy
  2. Откройте план. У планов с оплатой за IP (датацентр, ISP) список адресов, порты, логин и пароль лежат прямо на карточке, а кнопка Export отдаёт весь список текстом
  3. У резидентских и мобильных планов нажмите Options. Панель Proxy Configuration соберёт строку логина с вашей страной, городом и настройками сессии. Готовую строку копируйте из Proxy List
Кабинет GeekProxy, Subscriptions
Кабинет GeekProxy, страница Subscriptions: планы ISP со ссылкой Export, планы Residential Flex и Turbo с кнопками Options и Add GB

3 Go

Go самый простой. У http.Transport есть поле Proxy, оно принимает функцию, а http.ProxyURL делает такую функцию из разобранного URL. В описании поля перечислены схемы: http, https, socks5 и socks5h. Если в URL есть userinfo, транспорт сам отправит заголовок Proxy-Authorization.

proxyURL, _ := url.Parse("http://LOGIN:PASSWORD@IP:PORT") // или "socks5://LOGIN:PASSWORD@IP:PORT"
client := &http.Client{
	Timeout:   30 * time.Second,
	Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
}
resp, err := client.Get("https://ipinfo.io/json")

SOCKS5 с паролем: да, встроено, причём socks5 трактуется как socks5h, то есть имя хоста резолвит прокси. Никаких лишних пакетов. Пакет golang.org/x/net/proxy нужен только для сырого TCP: proxy.SOCKS5("tcp", "IP:PORT", &proxy.Auth{User: "LOGIN", Password: "PASSWORD"}, proxy.Direct) даёт dialer для SMTP, базы данных и любого другого сокета.

Можно вообще не трогать код. http.DefaultTransport использует http.ProxyFromEnvironment, который читает HTTPS_PROXY, HTTP_PROXY и NO_PROXY (нижний регистр важнее). Значение может быть полным URL, в том числе SOCKS5, или голым host:port, который считается HTTP. Две особенности из документации: запросы на localhost через прокси из окружения не идут никогда, а в CGI-процессе HTTP_PROXY отвергается намеренно.

main.go, Transport с ProxyURL
Редактор: программа на Go с http.Transport, где Proxy задан через http.ProxyURL, и GET на ipinfo.io

4 PHP

Расширение curl отдаёт опции libcurl один в один. CURLOPT_PROXY принимает хост, CURLOPT_PROXYPORT порт, CURLOPT_PROXYUSERPWD данные доступа строкой LOGIN:PASSWORD. CURLOPT_PROXYTYPE по умолчанию CURLPROXY_HTTP; для SOCKS5 с DNS на стороне прокси берите CURLPROXY_SOCKS5_HOSTNAME, а не просто CURLPROXY_SOCKS5, который резолвит имена у вас.

$ch = curl_init('https://ipinfo.io/json');
curl_setopt_array($ch, [
    CURLOPT_PROXY          => 'IP',
    CURLOPT_PROXYPORT      => PORT,
    CURLOPT_PROXYUSERPWD   => 'LOGIN:PASSWORD',
    CURLOPT_PROXYTYPE      => CURLPROXY_HTTP,   // CURLPROXY_SOCKS5_HOSTNAME для SOCKS5
    CURLOPT_PROXYAUTH      => CURLAUTH_BASIC,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT        => 60,
]);
$body = curl_exec($ch);

SOCKS5 с паролем здесь тоже работает. Данные доступа несёт тот же CURLOPT_PROXYUSERPWD. А вот переключатель метода аутентификации другой: CURLOPT_PROXYAUTH для HTTP-прокси (только Basic или NTLM), CURLOPT_SOCKS5_AUTH для SOCKS5, с PHP 7.3. libcurl принимает в CURLOPT_PROXY и полную строку socks5h://LOGIN:PASSWORD@IP:PORT; мануал PHP документирует там только хост, так что считайте эту форму документированной со стороны libcurl.

Guzzle заворачивает то же самое в опцию запроса proxy. Строка задаёт один прокси на все протоколы, массив задаёт прокси по схемам плюс список no. В документации сказано, что URL может нести схему, имя пользователя и пароль.

$client = new GuzzleHttp\Client(['timeout' => 30]);
$res = $client->request('GET', 'https://ipinfo.io/json', [
    'proxy' => [
        'http'  => 'http://LOGIN:PASSWORD@IP:PORT',
        'https' => 'http://LOGIN:PASSWORD@IP:PORT',
        'no'    => ['localhost'],
    ],
]);
echo $res->getBody();
ip.php, curl_setopt_array с опциями прокси
Редактор: PHP-скрипт с CURLOPT_PROXY, CURLOPT_PROXYPORT, CURLOPT_PROXYUSERPWD и CURLOPT_PROXYTYPE

5 Java

Java делит задачу надвое. Адрес прокси приходит из системных свойств или объекта Proxy, данные доступа из java.net.Authenticator. Свойства http.proxyUser не существует. Его ищут часами.

Теперь ловушка. С JDK 8u111 файл conf/net.properties поставляется со строкой jdk.http.auth.tunneling.disabledSchemes=Basic. По-русски: JDK отказывается слать Basic-данные в CONNECT, а это любая цель на https:// через HTTP-прокси. Ваш Authenticator даже не спросят, и вы получите 407. Очистите свойство до первого запроса, в коде или через -Djdk.http.auth.tunneling.disabledSchemes="" в командной строке.

System.setProperty("jdk.http.auth.tunneling.disabledSchemes", ""); // разрешить Basic в CONNECT

HttpClient client = HttpClient.newBuilder()
        .proxy(ProxySelector.of(new InetSocketAddress("IP", PORT)))
        .authenticator(new Authenticator() {
            @Override protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("LOGIN", "PASSWORD".toCharArray());
            }
        })
        .build();
HttpResponse<String> r = client.send(
        HttpRequest.newBuilder(URI.create("https://ipinfo.io/json")).build(),
        HttpResponse.BodyHandlers.ofString());
System.out.println(r.body());

Для всей JVM без кода: -Dhttps.proxyHost=IP -Dhttps.proxyPort=PORT -Dhttp.proxyHost=IP -Dhttp.proxyPort=PORT плюс Authenticator.setDefault(...) где-нибудь на старте. В таком глобальном аутентификаторе проверяйте getRequestorType() == RequestorType.PROXY, чтобы не отдать пароль от прокси какому-нибудь сайту.

SOCKS5 с паролем: да, на уровне сокетов. -DsocksProxyHost=IP -DsocksProxyPort=PORT -Djava.net.socks.username=LOGIN -Djava.net.socks.password=PASSWORD заворачивает каждый java.net.Socket, включая JDBC и SMTP. Сюрприз из документации: если данные доступа не заданы вообще, JDK отправит ваш user.name как имя пользователя SOCKS с пустым паролем. У HttpClient из JDK 11 SOCKS в документированном API нет, там держитесь HTTP.

OkHttp туннелирует сам и держит отдельный proxyAuthenticator. По документации аутентификатор вызывается всегда перед CONNECT с фиктивным 407 и челленджем OkHttp-Preemptive, так что данные уходят с первой попытки. От зацикливания защищает возврат null, когда у запроса уже есть заголовок Proxy-Authorization.

OkHttpClient client = new OkHttpClient.Builder()
    .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("IP", PORT)))
    .proxyAuthenticator((route, response) -> {
        if (response.request().header("Proxy-Authorization") != null) {
            return null; // сдаёмся, аутентификация уже не прошла
        }
        String credential = Credentials.basic("LOGIN", "PASSWORD");
        return response.request().newBuilder()
            .header("Proxy-Authorization", credential)
            .build();
    })
    .build();
Main.java, HttpClient с Authenticator
Редактор: программа на Java очищает jdk.http.auth.tunneling.disabledSchemes и собирает HttpClient с ProxySelector и Authenticator

6 C# и .NET

В .NET прокси это объект WebProxy, который отдают в HttpClientHandler. Данные доступа лежат в его свойстве Credentials как NetworkCredential. Документация отмечает, что прокси на уровне обработчика перекрывает настройки машины и конфига приложения.

var proxy = new WebProxy("http://IP:PORT")
{
    Credentials = new NetworkCredential("LOGIN", "PASSWORD"),
    BypassProxyOnLocal = true,
};
var handler = new HttpClientHandler { Proxy = proxy, UseProxy = true };
using var client = new HttpClient(handler);
Console.WriteLine(await client.GetStringAsync("https://ipinfo.io/json"));

SOCKS4, SOCKS4a и SOCKS5 появились в .NET 6. Выбираются они схемой в URI. Помните сноску из анонса про .NET 6: конструктор WebProxy(string) там умеет только HTTP, поэтому пишите new WebProxy(new Uri("socks5://IP:PORT")); в .NET 7 это поправили. SOCKS5 с паролем документирован в форме переменной окружения, socks5://LOGIN:PASSWORD@IP:PORT. Уходит ли свойство Credentials в SOCKS5-рукопожатие, документация не говорит. Нужно, берите форму с URL.

Переменные окружения накрывают каждый HttpClient без явного прокси через HttpClient.DefaultProxy. На Linux это единственный источник: нет переменных, нет прокси. Читаются HTTP_PROXY, HTTPS_PROXY, ALL_PROXY и NO_PROXY, сначала в нижнем регистре, и значение может содержать логин и пароль. В NO_PROXY нет масок; точка в начале матчит поддомены.

HTTPS_PROXY="http://LOGIN:PASSWORD@IP:PORT" HTTP_PROXY="http://LOGIN:PASSWORD@IP:PORT" dotnet run

Если прокси закрывает соединение вместо ответа 407, включите предварительную аутентификацию: System.Net.Http.SocketsHttpHandler.ProxyPreAuthenticate в runtimeconfig.json или переменная DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_PROXYPREAUTHENTICATE=1. Тогда Basic-данные уйдут с первым же запросом.

Program.cs, WebProxy с NetworkCredential
Редактор: программа на C# с WebProxy, NetworkCredential, HttpClientHandler и GET на ipinfo.io

7 Проверка работы

Каждый сниппет выше печатает тело https://ipinfo.io/json. Поле ip должно показать адрес прокси, а не ваш. На ISP или датацентре это адрес из кабинета, на Residential или Turbo любой адрес из пула в выбранной стране. Запустите ещё раз без прокси: другой ip значит, что прокси действительно был на пути.

8 Какой продукт GeekProxy подходит

Большая часть кода на этих четырёх языках это интеграции: API-клиент, бот, чекер на сервере. Им нужен один постоянный адрес без счётчика трафика, то есть статический ISP или датацентр IPv4, в режиме белого списка, если не хочется держать пароль в конфиге. Краулер на Go, PHP, Java или C# это другой случай: Residential Turbo или Residential Flex, ротация для охвата и sticky-логин, когда сессия должна удержать IP. Протокол по умолчанию HTTP. SOCKS5 оправдан, только когда через прокси должен идти не-HTTP протокол, скажем через x/net/proxy в Go или socksProxyHost в Java. Turbo даёт там SOCKS5; Flex выдаёт URL с socks5h и работает только по TCP.

9 Частые проблемы

Java: 407 или «Unable to tunnel through proxy» при верном пароле

Дефолт jdk.http.auth.tunneling.disabledSchemes=Basic. Очистите его до первого запроса или поправьте $JAVA_HOME/conf/net.properties.

PHP: SOCKS5 работает, но сайты с гео-балансировкой ведут себя неправильно

CURLPROXY_SOCKS5 резолвит DNS локально, и сайт выбирается по вашему местоположению. Переключитесь на CURLPROXY_SOCKS5_HOSTNAME.

.NET на Linux игнорирует системный прокси

С точки зрения .NET системного прокси на Linux нет. Задайте переменные окружения или явный WebProxy.

Go: прокси из окружения пропускается для одного хоста

localhost через прокси из окружения не ходит никогда, так задумано. Всё остальное слушается NO_PROXY, проверьте список.

407 везде

Не сходятся логин или пароль, либо план в режиме белого списка, а IP сервера в нём нет. В форме URL пароль кодируется процентами, в отдельных строковых опциях нет.

Не получается? Напишите нам в Telegram, Discord или в чат на сайте. Обычно отвечаем в течение нескольких минут.

Прокси для вашего бэкенда

Статические ISP и датацентр для интеграций, ротируемые резидентские для краулеров, HTTP и SOCKS5.

Заказать

We use cookies to improve user experience. By clicking "Yes, I agree", you consent to this use of cookies.

Привилегия первых: В честь глобального запуска [мы даем скидку 50%+] на все датацентр тарифы. Эксклюзивное предложение для наших стартовых партнеров.