4

Is it possible to establish ssh connection through proxy using php?

My php code is

$connection = ssh2_connect('x.x.x.x');

But it gives an error below

PHP Warning:  ssh2_connect(): Unable to connect to x.x.x.x

I can't establish ssh connection via command line too.

ssh root@x.x.x.x

Solution (FAIL)

Then I found solution. I created **~/.ssh/config** file and added Proxy definitions to it.

Host x.x.x.x
    Hostname x.x.x.x
    User root
    ProxyCommand /usr/bin/corkscrew proxy.somewebsite.com 10080 %h %p

After that I was able to connect to ssh via command line :)

But I can't still connect with php code. I still get the same error :(

Problem here is that ssh2_connection function doesn't using ssh config file. Is there a way to tell the function to use it?

Farid Movsumov
  • 12,350
  • 8
  • 71
  • 97

2 Answers2

2

Indeed possible and quite simple using phpseclib. Was using php ssh2 prior and was working fine but no known way to establish connection via proxy. phpseclib comparatively better than php's ssh2. This means no ssh2_connect if that is what you are using. Here's sample code that is working for me:

public function connect()
        {
            $auth = base64_encode($this->proxyUser.':'.$this->proxyPass);

            $fsock = fsockopen($this->proxyHost, $this->proxyPort);
            $request = "CONNECT $this->ssh_host:$this->ssh_port HTTP/1.0\r\nContent-Length: 0\r\nProxy-Authorization: Basic $auth\r\n\r\n";

            if(fputs($fsock, $request) != strlen($request)) {
                sys_error("Unable to connect to proxy");
            }

            $response = fgets($fsock); //Response should be 'Connection Established'

            $this->sftp = new Net_SFTP($fsock);  //Will work similarly for Net_SSH

            if(!$this->sftp->login($this->ssh_auth_user, $this->ssh_auth_pass)){
                sys_error('Login to sftp server failed');
                return false;
            }

            return true;
        }
0

So you're tunneling the connection to x.x.x.x through Corkscrew, which, I'm assuming, requires HTTP CONNECT proxies to work.

HTTP CONNECT is a fairly simple protocol so I'll let you figure that out but, once you have, you can use phpseclib (which I should note you're not actually using in your orig post) to alter the socket object - to kinda prep the socket object. ie. so instead of passing the hostname and port number to the constructor you pass the socket. Example code:

<?php
// http://us3.php.net/manual/en/context.socket.php
$opts = array(
    'socket' => array(
        'bindto' => '192.168.1.100:0',
    ),
);
$context = stream_context_create($opts);
$socket = stream_socket_client('tcp://example.net:80', $errno, $errstr, ini_get('default_socket_timeout'), STREAM_CLIENT_CONNECT, $context);

$ssh = new Net_SSH2($socket); 

More info:

https://github.com/phpseclib/phpseclib/issues/742#issuecomment-122351289

neubert
  • 15,947
  • 24
  • 120
  • 212
  • Thanks @neubert I am not able try it right now. I will try it monday and let you know result. – Farid Movsumov Jun 05 '16 at 06:42
  • Post your code. What I posted wasn't a proper HTTP CONNECT client - what I posted was an example of how to make changes to the socket resource that phpseclib will utilize. The changes you'd need to make are different than the ones in my post. My post was just an example of how to use a modified socket. – neubert Jun 07 '16 at 14:19
  • I already modified your code to match my requirements but unfortunately it doesn't work for me. I don't have that code right now sorry. – Farid Movsumov Jun 08 '16 at 11:09