guzzle: Proxying via socks5 (simple ssh tunnel) doesn't work

I can’t connect via socks5 proxy. Guzzle version = 6.1.0. The configuration is done like this:

$http_options['proxy'] = 'tcp://127.0.0.1:12345'

but I get the following error: failed to open stream: Cannot connect to HTTPS server through proxy [file] <…>/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php

I also tried using ‘socks5’ scheme, but it doesn’t seem to be defined:

$http_options['proxy'] = 'tcp://127.0.0.1:12345'

Unable to find the socket transport "socks5" - did you forget to enable it when you configured PHP?

I also tried configuring ‘curl’ like this:

$http_options['curl'] = [CURLOPT_PROXY => 'socks5://127.0.0.1:12345'];

but this is just ignored by Guzzle.

So how it is supposed to be working?

I should say that making the same request via pure cURL PHP lib or curl command line works fine.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 25 (8 by maintainers)

Most upvoted comments

@itbdw replace scheme socks5 with socks5h. So try this:

$client = new GuzzleClient();
$result = $client->get($url, ['proxy'=>"socks5h://127.0.0.1:1080", 'timeout'=>1]);
$result = $client->get('https://google.com', ['proxy'=>"socks5://127.0.0.1:1080", 'timeout'=>1]);

echo $result->getBody();

Then reason that above code works fun for @sagikazarmark but not for @itbdw is DNS difference. When using socks5, hostname will be resolved locally. GET https://google.com will be redirected to https://www.google.com. But DNS cannot resolve right ip of www.google.com in circumstance of @itbdw. When using socks5h, hostname will be resolved by proxy.


$ch = curl_init('https://google.com');
curl_setopt($ch, CURLOPT_PROXY, "socks5://127.0.0.1:1080");

Because guzzle default allow redirects but curl doesn’t. So if above code works, following code may work also.

$result = $client->get('https://google.com', ['proxy'=>"socks5://127.0.0.1:1080", 'timeout'=>1 'allow_redirects' => false]);

echo $result->getBody();

The issue for me is that the socks5:// proxy scheme only works with CurlHandler, which is fine most of the time, until you start using the stream option: Guzzle then transparently switches to the StreamHandler, which supports streaming but does not support socks5:// or socks5h://, and does not seem to support SOCKS5 via the tcp:// scheme either.

So you’re using your SOCKS5 proxy with Guzzle and everything works fine. Then you attempt to stream a response and you suddenly get:

Error creating resource: [message] fopen(http://…): failed to open stream: Unable to find the socket transport “socks5h” - did you forget to enable it when you configured PHP?

This is all very confusing and should at least be documented.

for me work with SOCKS5 protocol. need to setup option like this

$httpClient = new GuzzleHttp\Client([
    'proxy' => '127.0.0.1:1080', //use without "socks5://" scheme
    'verify' => true, // used only for SSL check , u can set false too for not check
    'curl' => [CURLOPT_PROXYTYPE => 7],
]);

What should I do if just wanna add configuration below.

This works fun

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_PROXY, "socks5://127.0.0.1:1080");
        ...

While this one does not

        $client = new GuzzleClient();
        $result = $client->get($url, ['proxy'=>"socks5://127.0.0.1:1080", 'timeout'=>1]);

it said, Exception Found:GuzzleHttp\Exception\ConnectException 0: cURL error 28: Operation timed out after 1001 milliseconds with 0 bytes received (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in file /home/vagrant/Code/web/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php on line 186

So, this is not the first time this issue comes up, but it’s not one issue really.

cURL options are not used

failed to open stream: Cannot connect to HTTPS server through proxy [file] <…>/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php

Since in this case you don’t actually use cURL, it’s no surprise that curl options doesn’t work for you.

Although stream contexts support proxy option, I am not 100% sure that it supports authentication too.

So you need to make sure that you actually use the cURL handler.

socks5:// transport doesn’t work

I believe you can just use tcp://

Authentication

As said above I am not 100% sure that stream contexts support authentication.

As for cURL, it does, but not sure it understands the tcp://user:pass@host:port form.

See:

For the moment you can pass these configurations as curl options.

An alternative solution would be to parse the proxy URL and see if it contains a user/password pair, but that still lacks the authentication method. First I would try using the curl options above (see the PHP constants here: http://php.net/manual/en/curl.constants.php)

/cc @DenoBY