Created
February 18, 2017 09:06
-
-
Save skunkbad/a07e86248e2bce80cf3092cbe652c829 to your computer and use it in GitHub Desktop.
Attempt to use an SSH tunnel to connect to MySQL on a remote host
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/*** | |
Based off code from: | |
https://www.experts-exchange.com/questions/26619790/Connect-to-Mysql-through-PHP-ssh2-tunnel.html | |
Example usage: User/Pass Based Auth MySQL Proxy | |
----------------------------------------------- | |
$user_pass_config = array( | |
'user' => 'username', | |
'pass' => 'password', | |
'host' => 'myserver.com', | |
'port' => 22 | |
); | |
$local_proxy_port = 3307; | |
$remote_proxy_host = '127.0.0.1'; | |
$remote_proxy_port = 3306; | |
$tunnel = new Tunnel(); | |
$tunnel->set_config( $user_pass_config ); | |
$tunnel->proxy( $local_proxy_port, $remote_proxy_host, $remote_proxy_port ); | |
// We now have a tcp server on 127.0.0.1 port 3307 which is proxying, over ssh, to 127.0.0.1 port 3306 on myserver.com | |
**/ | |
class Tunnel { | |
public $host = NULL; // SSH Host | |
public $port = 22; // SSH Port | |
public $user = NULL; // Username | |
public $pass = NULL; // User Password | |
private $conn = NULL; // Resource: SSH2 connection | |
private $tunnel = NULL; // Resource: SSH2 tunnel | |
private $socket = NULL; // Local socket | |
private $debug_array = []; // Debug messages | |
// ----------------------------------------------------------------------- | |
public function __construct(){ return $this; } | |
// ----------------------------------------------------------------------- | |
public function set_config( $args = [] ) | |
{ | |
foreach( $args as $k => $v ) | |
$this->$k = $v; | |
return $this; | |
} | |
// ----------------------------------------------------------------------- | |
public function proxy( $local_port, $remote_host, $remote_port ) | |
{ | |
if( ! $this->_connect_to_remote_server( $remote_host, $remote_port ) ) | |
return FALSE; | |
if( ! $this->_create_local_socket( $local_port ) ) | |
return FALSE; | |
$conn = @stream_socket_accept( $this->socket, 180 ); | |
stream_set_blocking( $conn, FALSE ); | |
while( ! feof($conn) && ! feof($this->socket) ) | |
{ | |
// Read from server to client | |
if ( strlen( $data = @fread( $this->tunnel, 4096 ) ) ) { | |
if ( FALSE === fwrite( $conn, $data ) ) | |
break; | |
} else if ( strlen( $data = @fread( $conn, 4096 ) ) ) { | |
if ( FALSE === fwrite( $this->tunnel, $data ) ) | |
break; | |
} else { | |
usleep( 5000 ); | |
} | |
} | |
@fclose( $conn ); | |
@fclose( $this->tunnel ); | |
return TRUE; | |
} | |
// ----------------------------------------------------------------------- | |
private function _connect_to_remote_server( $remote_host, $remote_port ) | |
{ | |
if( ! $this->_connect() ) return FALSE; | |
if( $this->tunnel ) | |
return TRUE; | |
$this->tunnel = fopen("ssh2.tunnel://$this->conn/$remote_host:$remote_port", 'r+'); | |
if( ! $this->tunnel OR ! is_resource( $this->tunnel ) ) | |
{ | |
$this->debug_array[] = "Failed Initializing Tunnel To $remote_host:$remote_port"; | |
return FALSE; | |
} | |
$this->debug_array[] = "Tunnel To $remote_host:$remote_port Initialized"; | |
stream_set_blocking( $this->tunnel, FALSE ); | |
return TRUE; | |
} | |
// ----------------------------------------------------------------------- | |
private function _connect() | |
{ | |
if( $this->conn ) | |
return $this->conn; | |
if( ! $this->host OR ! $this->port OR ! $this->user OR ! $this->pass ) | |
return FALSE; | |
$this->conn = ssh2_connect( $this->host, $this->port ); | |
if( ! $this->conn ) | |
{ | |
$this->conn = NULL; | |
$this->debug_array[] = "Could not connect to $this->host:$this->port"; | |
return FALSE; | |
} | |
$this->debug_array[] = "Connected to $this->host:$this->port"; | |
$auth = ssh2_auth_password( $this->conn, $this->user, $this->pass ); | |
if( ! $auth ) | |
{ | |
$this->conn = NULL; | |
$this->debug_array[] = "Could not authenticate for user $this->user"; | |
return FALSE; | |
} | |
$this->debug_array[] = "Logged in as $this->user"; | |
return TRUE; | |
} | |
// ----------------------------------------------------------------------- | |
private function _create_local_socket( $port ) | |
{ | |
$this->socket = stream_socket_server( "tcp://127.0.0.1:$port", $errno, $errstr ); | |
if( ! $this->socket ) | |
{ | |
$this->debug_array[] = "Failed creating socket server: $errstr ($errno)"; | |
return FALSE; | |
} | |
return TRUE; | |
} | |
// ----------------------------------------------------------------------- | |
public function halt() | |
{ | |
$this->conn = NULL; | |
@fclose( $this->tunnel ); | |
die('<pre>' . print_r( $this->debug_array, TRUE ) . '</pre>'); | |
} | |
// ----------------------------------------------------------------------- | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment