Archive

Archive for the ‘PHP’ Category

PHP SSH2: Bindings for the libssh2 library

December 8th, 2010 2 comments

PHP has bindings to the libssh2 library which provide access to resources (shell, remote exec, tunneling, file transfer) on a remote machine using a secure cryptographic transport. This tutorial will show you how to make SSH2 connections from PHP to execute commands over SSH. This requires the SSH2 PECL extension to be installed on your machine.

Installing PHP-SSH2

In the latest Debian/Ubuntu builds you can install PHP-SSH2 using apt.

$ sudo aptitude install libssh2-php

Compile from source.

You can find the latest PHP-SSH2 source files here. You will require libssh2 dev files to compile the PHP-SSH2 module.

First install the libssh2 dev files.

$ sudo aptitude install libssh2-1-dev

Now download the php-ssh2 source file and compile it.

$ wget http://pecl.php.net/get/ssh2-0.11.2.tgz
$ tar xfz ssh2-0.11.2.tgz
$ cd ssh2-0.11.2
$ phpize && ./configure && make
$ sudo make install

You might require to copy the ‘ssh2.so’ file to proper path to call the dl() function.

Working With PHP-SSH2

Working with php-ssh2 is fairly straightforward. The ssh2_connect function will establish a connection to a remote SSH server. Once connected, the client should verify the server’s hostkey using ssh2_fingerprint(), then authenticate using either password or public key.

First make a SSH connection..

$hostname = 'example.com';
 
$con = @ssh2_connect($hostname, 22);
if(!$con) die('Cannot Connect...');

The ssh2_connect will return a resource on success that we will pass to the next functions.

Now we have to authenticate as a user. You either use a username and password or use public key and private key for authentication.

Authentication using username and password.

$username = 'username';
$password = 'secret';
 
if(!@ssh2_auth_password($con, $username, $password))
  die('Authentication Failed...');

Authentication using a public key. If privkeyfile is encrypted (which it should be), the passphrase must be provided.

$hostname = 'example.com';
$username = 'username';
$passphrase = 'secret';
 
$con = @ssh2_connect($hostname, 22, array('hostkey'=>'ssh-dss'));
if(!$con) die('Cannot Connect...');
 
if(!@ssh2_auth_pubkey_file($con, $username, '/home/$username/.ssh/id_dsa.pub', '/home/$username/.ssh/id_dsa', $passphrase))
  die('Authentication Failed...');

Now that we are connected and authenticated, we can send a command:

$stream = @ssh2_exec($con, "ls -la" );
 
stream_set_blocking($stream, true);
 
while ($buf = fread($stream,4096)) {
    $data .= $buf;
}
fclose($stream);
 
print $data;

The ssh2_exec function will return a stream on success. The command may not finish before the function return if the stream is not set to blocking mode. You may have to set the stream to blocking mode in order to get any output from the command.

Using sudo in commands

The -S (stdin) option causes sudo to read the password from the standard input instead of the terminal device.

$stream = @ssh2_exec($con, "echo $password | sudo -S $cmd" );

The Shell Mode

The ssh2_shell will open a shell at the remote end and allocate a stream for it. Using ssh_exec, one could execute only one command at a time. However, ssh_shell, offers greater flexibility.

Here is an example:

$shell = ssh2_shell($con, 'xterm');
fwrite( $shell, "cd /dir_one\n");
fwrite( $shell, "ls -la\n");
fwrite( $shell, "cd /dir_two\n");
fwrite( $shell, "ls -la\n");
 
stream_set_blocking($shell, true);
while($line = fgets($shell)) {
        flush();
        echo $line;
}
fclose($shell);

Using SCP to transfer files

The ssh2_scp_send function will copy a file from the local filesystem to the remote server using the SCP protocol.

$username = 'username';
$password = 'secret';
 
$con = @ssh2_connect($hostname, 22);
if(!$con) die('Cannot Connect...');
 
if(!@ssh2_auth_password($con, $username, $password))
  die('Authentication Failed...');
 
ssh2_scp_send($con, '/tmp/httpd.conf', '/usr/local/apache2/conf/httpd.conf', 0644);

The ssh2_scp_recv function copy a file from the remote server to the local filesystem using the SCP protocol.

ssh2_scp_recv($con, '/usr/local/apache2/conf/httpd.conf', '/tmp/httpd.conf');

SCP a directory

You will need to write your own functions using ssh2_scp_send and ssh2_scp_recv for recursive file transfer. Here is a quick and dirty recursive scp function.

function ssh2_scp_send_recursive($con, $local_path, $remote_path)
{
    if(substr($local_path,-1) !== '/'){$local_path .= '/';}
    if ($handle = opendir($local_path)){
        while (false !== ($file = readdir($handle))){
            if($file == "." || $file == "..") continue;
            if (filetype($local_path.$file) === 'dir'){
                clearstatcache();
                ssh2_exec($con, "mkdir -p " . $remote_path . $file);
                ssh2_scp_send_($con, $local_path . $file, $remote_path);
            } else {
                ssh2_scp_send($con, $local_path . $file, $remote_path . $file);
            }
        }
        closedir($handle);
    }
}

Refer the PHP-SSH2 manual for more details.

Happy SSHing. :-)

Categories: PHP Tags: