2

I have a central system(web application) which is supposed to connect to a set of nodes one by one (clients), to get a record set from database exposed through mysql views.

I am in a search of best possible implementation for this scenario. Currently I have this flow in my mind.

1. First Approach

Pseudo code

 $dataFetched=array();
  $clients= getListOfClients();
  //
  foreach($clients as $client){
   // client={details:{id,name,etc....},
   //         ssh:{pem:'client.pem',localMysqlPort:3307 ,remoteMyqlPort:3306,
   //              sshUser:'demo@clientHost.com'},
   //         mysql:{user:'tunnelUser',password:'password'}
   //        }
   //connect ssh connection
   $ssh_connection=new Ssh_connect($client->ssh) 
   if($ssh_connection->status){    
      $dataFetched[$client->id]=array("status"=>'OK','data'=>fetchMysqlData($client->mysql))
   }else{
      $dataFetched[$client->id]=array("status"=>'NO_OK','data'=>array())
   }

   $ssh_connection->destroyTunnel();
   unset($ssh_connection);   
  }

Some Concerns/questions with this approach

  1. Is there a ssh lib/extension to provide me this kind of functionality ?

  2. What is best secure way to store "pem" files for each client ?

  3. Another approach ?

2. Second Approach

  1. Write bash script to implement above pseudo-code

  2. setup cron job to update database

  3. Web application does not know about external clients. It will use table updated by cron-job to render data.

Some point:

  1. Data size is very light

  2. Both consumer and provider are web-applications

  3. Applications does not know each other except SSH

  4. It should be flexible to add new client node ( I don't known how I will do this in second approach)

  5. Which one will be better from security wise Reverse Tunnel or Forward Tunnel ? As I know in case of reverse tunnel, echo client knows about server which desires to connect with it. So we need to setup a less privileged user to on each client node to give access to server, which seems more secure as I don't have to keep all pem files in one place at Central server. Correct me if I am getting it wrong.

Your suggestions are much appreciated

sakhunzai
  • 13,900
  • 23
  • 98
  • 159
  • 1
    Is there a particular reason for choosing PHP over others (and probably more suitable) tools, to do this? – Loïc Feb 28 '14 at 05:30
  • The application is written in php, but I am open to other suggestions as far as its supported by *nix system ( ubuntu currently) by default. – sakhunzai Feb 28 '14 at 05:59
  • I would then suggest Python which would be much more adapted to do the job in my opinion. (check http://www.lag.net/paramiko/) – Loïc Feb 28 '14 at 06:36
  • In your first approach, are you suggesting that you want your web application (running as the www or www-data user) to have ssh access to remote servers? And are you saying that the data you want to fetch from the remote servers is made available as the output from a CLI `mysql` that you access via SSH? Or does "*Both consumer and provider are web-applications*" mean that you can access the remote data via HTTPS? – ghoti Feb 28 '14 at 16:28
  • You can't really tunnel SQL through SSH in PHP. Best you'd be able to do is something like this: http://stackoverflow.com/a/18331867/569976 . That said I'd recommend phpseclib. With libssh2 you have to have the public and private keys both living on the filesystem. With phpseclib they can be in the PHP script itself and you can adjust the permissions for that as you see fit. So it's one less issue for you to worry about. – neubert Feb 28 '14 at 19:34

1 Answers1

1

There is an SSH library for PHP. It's called ssh2 and it is available on PECL.

It has a dependancy on libssh2, but it should not be too hard to get up and running on a Linux-based machine.

The best way to store the pem files is outside your web directory, with limited permissions - just enough for your web application to be able to read the files. Alternatively, you could set up the ssh-agent daemon to run as your web application.

(I am hoping here that your PHP apps don't all run under the same user. For Apache, there is the little known mod_ruid2 module that allows you to change the user and chroot a PHP web app, without resorting to setting up fastcgi or suExec).

Sadly, ssh2_tunnel only creates a new PHP resource, it's not something that you can use to create a new mysql connection (well, at least not using mysqli_connect & friends).

What you could do is execute the SQL commands on the local server, storing the database password inside ~/.my.cnf

~/.my.cnf:

[client]
password = lolcats1234

And then with PHP & ssh2 you could run the following code once connected:

stream_set_blocking($stream, true); 
$stream = ssh2_exec($connection, 'mysql -u db -p db -e "select * from table"');

$first = true;
while($line = fgets($stream)) {
     if ($first) {
          $first = false;
          continue;
     }

     // process one line of results...
     echo $line."<br />"; 
} 

Alternatively, if you just use a Reverse Tunnel, you can just mysql_connect using the local script, without needing to worry about doing any SSH work at all.

Tim Groeneveld
  • 8,739
  • 3
  • 44
  • 60
  • 1
    Well I dont think I ll be using this way(ssh2). I have decided to use reverse tunneling as you suggested in last para, from client on specified port to server.check this : http://unix.stackexchange.com/questions/117405/creating-a-linux-user-with-limited-privileges-for-ssh-tunnelling – sakhunzai Mar 03 '14 at 12:38
  • Yeah, that is a much easier way to achieve the same goal. – Tim Groeneveld Mar 03 '14 at 15:03