Reply to comment

SSH with PHP 5

There are many cool things your can do if you have SSH with PHP. PHP 5 does not include this feature in its core distribution. So how can you do it?

One solution is to make use of the ssh2 package from PECL. The package provides several useful methods for secure remote access. Unfortunately, sometimes you may not be able to use the package due to some pragmatic problems. If you do not have privileged access to the server, and if you fail to convince the admin to install the package or the libraries required to compile it, you won't be able to use it (as well as many other PECL packages).

To solve this problem, I've written some code that requires only the following items to use SSH with PHP:

  • The SSH binary. (Normally found at /usr/bin/ssh.)
  • PHP 5. (However the script can be ported to PHP 4 easily.)
  • Strong understanding of the security issues involved! NO WARRANTY IS PROVIDED. Some security issues involved are beyond the control of the script and thus it's your responsibility to make sure that your server is properly protected!

1. Preparation

You need to prepare your server with a few things before you can make sure of the script.

  1. Setup Passwordless SSH Access. Configure the web server and the remote machine such that the server is able to login to the remote machine with a key pair instead of making use of password. I have written a post on how to do it.
  2. Create a safe working directory for Apache. Make sure that it's safe:
    • No other accounts except the two used by the Apache process and you are able to access the directory. Set the permission very carefully.
    • Don't put it in any directory under the Apache's DocumentRoot to make sure that no public user can even peek at the directory. Include a file .htaccess with a single line of DENY from ALL for extra protection.
  3. Prepare the file with private key to be accessible by Apache. Copy the file ~/.ssh/id_rsa to a safe place such as the working directory prepared above. Set the file ownership and permission carefully. For even better security, encrypt the private key. Modify the code to decrypt the key with a user-supplied password when needed. Be warned that if you lose the private key and do not respond in time, your machines are in great risk!

2. The PHP Class

Here it goes.

<?php
/*
A PHP Class for using SSH
Copyright (C) 2007  http://www.vyvy.org/

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
/* Changes:
 *   [29-Jan-07]  First release
 */

/*----------------------------------------------------------------*/
/* Configuration                                                  */
/*----------------------------------------------------------------*/
define('PATH_SSH', 'ssh');  // Path to SSH binary

/*----------------------------------------------------------------*/
/* Implementation                                                 */
/*----------------------------------------------------------------*/
define('SSH_ERROR_SSH_CONFIG', 0x1);


class vyvy_ssh
{
  private \$user;
  private \$host;
  private \$file_ssh_key;
  private \$file_ssh_config;
  private \$file_known_hosts;
  private \$error = 0;


  function __construct(\$user, \$host, \$dir_ssh, \$file_ssh_key)
    {
      \$this->user = \$user;
      \$this->host = \$host;
      \$this->file_ssh_key = \$file_ssh_key;  // For better security, you may want to encrypt this file and decrypt it when needed.

      /* SSH configuration */
      \$this->file_ssh_config = tempnam(\$dir_ssh, 'config_');
      \$this->file_known_hosts = tempnam(\$dir_ssh, 'hosts_');
      \$size = file_put_contents(\$this->file_ssh_config,
                                "StrictHostKeyChecking no\n"
                                . "UserKnownHostsFile {\$this->file_known_hosts}\n"
                                . "Protocol 2");
      if (!\$size) {
        \$this->error |= SSH_ERROR_SSH_CONFIG;
      }
    }


  function __destruct()
    {
      /* Delete temporary files */
      exec('shred --remove '.\$this->file_ssh_config);
      exec('shred --remove '.\$this->file_known_hosts);
    }


  function exec(\$command, \$wait=true)
    {
      if (\$this->error) {
        return array(false, 0);
      }

      \$cmd = PATH_SSH . " -n -F {\$this->file_ssh_config} -i {\$this->file_ssh_key} {\$this->user}@{\$this->host} 'sh -c \"{\$command}\"'";
      if (!\$wait) {
        \$cmd .= ' > /dev/null &';
      }

      exec(\$cmd, \$output, \$error);

      if (\$error) {
        return array(false, \$error);
      }
      return array(true, \$output);
    }
}
?>

3. Example

The following example lists the files of a remote machine. It's quite simple to use, isn't it?

<?php
require_once "vyvy_ssh.php";

\$ssh = new vyvy_ssh('vyvy', '10.0.0.7',
                    '/home/vyvy/www_private/ssh/',
                    '/home/vyvy/www_private/id_rsa');
list(\$status, \$output) = \$ssh->exec('ls -las');

\$output_formatted = htmlspecialchars(implode("\n", \$output));

echo <<<PAGE
<html>
  <head>
    <title>Sample Output</title>
  </head>
  <body>
<p>Status: {\$status}</p>
<p>Output:</p>
    <pre>
{\$output_formatted}
    </pre>
  </body>
</html>
PAGE;
?>

Reply

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.