PHP : ssh2 : How to connect to a second ssh server - php

I have to connect to a server via ssh, but to access it I need to first connect to another ssh server. I use standard password access to them.
So my steps are:
ssh root#serverdomain1.com
then when connected in serverdomain1 I do in terminal:
ssh myuseraccount#serverdomain2.com
in php, I tried to use ssh2_exec('ssh serverdomain2.com'); but no results. Then I tried also ss2_tunnel($connection, ...). but nothing worked.
This doesn't work:
$ssh = ssh2_connect('serverdomain1.com', 22);
if (ssh2_auth_password($ssh, $user,$pass)) {
$stream = ssh_exec($ssh, "ssh serverdomain2.com");
stream_set_blocking($stream, true);
$stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
echo stream_get_contents($stream_out); // <== doesn't work!!!
}
This also doesn't work:
$ssh = ssh2_connect('serverdomain1.com', 22);
if (ssh2_auth_password($ssh, $user,$pass)) {
$tunnel = ssh2_tunnel($ssh, 'serverdomain2.com', 22);
if (!$tunnel) {
echo('no tunnel<br/>');
}
else {
fwrite($tunnel, "echo 1\n");
while (!feof($tunnel)) {
echo fgets($tunnel, 128);
}
}
}
The echo result for tunnel:
"SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.4 Protocol mismatch."
How can I do that with SSH2 from PHP?

I recently published a project that allows PHP to obtain and interact with a real Bash shell, through SSH if needed. Get it here: https://github.com/merlinthemagic/MTS
The project lets you keep bouncing from server to server using ssh.
After downloading you would simply use the following code:
//first you get a shell on the first server:
$shellObj = \MTS\Factories::getDevices()->getRemoteHost('ip_address1')->setConnectionDetail('username1', 'password1')->getShell();
//then build on that first shell, the following way.
\MTS\Factories::getDevices()->getRemoteHost('ip_address2')->setConnectionDetail('username2', 'password2')->getShell($shellObj);
//any command executed on the shell will run only on the second host you connected to.
$return1 = $shellObj->exeCmd("hostname");
echo $return1;//hostname of the second host you connected to
//

Make sure that RSSH, PECL, SSH2 libraries installed on your server
You can check this using phpinfo
Here is my working code to access the server using ssh2. Hope it will help!
<?php
$host = 'SERVER_HOST_ADDR';
$port = SERVER_PORT;
$username = 'SERVER_USERNAME';
$password = 'SERVER_PASSWORD';
$remoteDir = './home/'; //DIR_PATH
$localDir = '/var/www/html/'; //LOCAL_DIR_PATH
// Make our connection
$connection = ssh2_connect($host);
// Authenticate
if (!ssh2_auth_password($connection, $username, $password)) {
throw new Exception('Unable to connect.');
}
// Create our SFTP resource
if (!$sftp = ssh2_sftp($connection)) {
throw new Exception('Unable to create SFTP connection.');
}
/**
* Now that we have our SFTP resource, we can open a directory resource
* to get us a list of files. Here we will use the $sftp resource in
* our address string as I previously mentioned since our ssh2://
* protocol allows it.
*/
$files = array();
$dirHandle = opendir("ssh2.sftp://$sftp/$remoteDir");
// Properly scan through the directory for files, ignoring directory indexes (. & ..)
while (false !== ($file = readdir($dirHandle))) {
if ($file != '.' && $file != '..') {
$files[] = $file;
}
}
echo "<pre>";print_r($files);
?>

Related

Obtaining files via ssh2_scp_recv in php

For a project i need to retreive all the files on a sftp server with a total size that amounts to about ~100 mb among all the files. I developed a script thats uses the ssh2 library and fread to get all the files, but it takes arround 10 min to get all the content. I tried ssh2_scp_recv, hoping for better performance, as shown in code bellow, but the script runs rather fast, not obtaining any file, as if the mentioned function never ran.
function get_sftp_content(){
$url = 'someurl.com';
$port = 22;
$username = "user";
$password = "password";
// Make our connection
$connection = ssh2_connect($url);
// Authenticate
if (!ssh2_auth_password($connection, $username, $password)) throw new Exception('Unable to connect.');
// Create our SFTP resource
if (!$sftp = ssh2_sftp($connection)) throw new Exception('Unable to create SFTP connection.');
$localDir = '/ftp_files';
$remoteDir = '/download';
// download all the files
$files = scandir('ssh2.sftp://' . $sftp . $remoteDir);
//echo '<pre>' . print_r($files, true) . '</pre>' ;
if (!empty($files)) {
foreach ($files as $file) {
ssh2_scp_recv($connection,$remoteDir.'/'.$file, $localDir.'/'.$file);
}
}
}
get_sftp_content();
Any ideas on why this happens, and is there a faster alternative to get all the files, without recurring to phpseclib?

Use ssh2_exec() to extract a tar file in the "/" directory of a remote server

Am trying to extract a .tar file in the "/" directory of a remote server (server2), using the ssh2_exec() function from a php file located in another server (server1).
php file in server1:
<?php
$p_main_ip = 'xxx.xxx.xxx.xxx'; // ip of the server2
$user = 'root';
$p_password = 'password'; // server2 root password
$connection = ssh2_connect($p_main_ip, 22);
if($connection)
{
if(ssh2_auth_password($connection, $user, $p_password))
{
$stream = ssh2_exec($connection, 'tar xvpfz /home/t.tgz -C /');
}
}
?>
PS : I was able to extract the file in "/home" directory using this:
$stream = ssh2_exec($connection, 'tar xvpfz /home/t.tgz -C /home');
Thank you.

SSH2 what am I doing wrong?

I'm having trouble copying a file from my laravel project to another server. This is what I'm doing.
$connection = ssh2_connect($this->ftpHostname, $this->ftpPort);
if (!$connection) {
throw new \Exception("Couldn't connect to {$this->ftpHostname}:{$this->ftpPort}");
}
$loginResult = ssh2_auth_password($connection, 'usrname', 'pswrd');
if (!$loginResult) {
throw new \Exception("Username or Password not accepted for {$this->ftpHostname}:{$this->ftpPort}");
}
$sftp = ssh2_sftp($connection);
$fullFilePath = storage_path() .'/'.$this->argument('local-file');
$remoteFilePath = "ssh2.sftp://{$sftp}/{$this->argument('remote-folder')}/SomeFolder/{$this->argument('remote-filename')}.txt";
$copyResult = copy($fullFilePath, $remoteFilePath);
But it's giving me this error
[ErrorException]
copy(): Unable to open ssh2.sftp://Resource id #621/My Folders/Upload only/sample.txt on remote host
I'm really new in ssh how do I solve this?
Cast $sftp to an int before using it in the ssh2.sftp:// fopen wrapper.
$remoteFilePath = "ssh2.sftp://" . (int)$sftp . "/{$this->argument('remote-folder')}/SomeFolder/{$this->argument('remote-filename')}.txt";
From ssh2_sftp
The example code above fails unless you cast the $stftp to (int) or use intval()
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r'); // Fails
$stream = fopen("ssh2.sftp://" . (int)$sftp . "/path/to/file", 'r'); // joy
Since copy() will be using the fopen wrappers to interpret your ssh2.sftp:// uri, that should help.

I am creating PHP page in which i am downloading .CSV file from SFTP server

I want to download file from SFTP so i created page which looks like it.
<?php
$username = "XYZ";
$password = "ABC";
$url ='FTP.abc.COM';
// Make our connection
$connection = ssh2_connect($url);
// Authenticate
if (!ssh2_auth_password($connection, $username, $password)) throw new Exception('Unable to connect.');
// Create our SFTP resource
if (!$sftp = ssh2_sftp($connection)) throw new Exception('Unable to create SFTP connection.');
$localDir = '/path/to/your/local/dir';
$remoteDir = '/path/to/your/remote/dir';
// download all the files
$files = scandir('ssh2.sftp://' . $sftp . $remoteDir);
if (!empty($files))
{
foreach ($files as $file) {
if ($file != '.' && $file != '..')
{
ssh2_scp_recv($connection, "$remoteDir/$file", "$localDir/$file");
}
}
}
?>
When i will call this page from browser. It will show error look like it.
Fatal error: Call to undefined function ssh2_connect() in page.php on line 6
if this method is correct then what should i edit in this page?
and if there is another method then suggest me that method. Thanks in advance.
You'll probably have better success with phpseclib, a pure PHP SFTP implementation. eg.
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
// outputs the contents of filename.remote to the screen
echo $sftp->get('filename.remote');
// copies filename.remote to filename.local from the SFTP server
$sftp->get('filename.remote', 'filename.local');
?>
It has a number of advantages over libssh2:
http://phpseclib.sourceforge.net/ssh/compare.html
SSH2 functions are not standard functions in PHP. You have to install them first. See http://php.net/manual/en/ref.ssh2.php for more details.

Delete Folder With Contents In SSH Server

I'm trying to delete a folder and all the files that in it, in a SSH server.
The thing is that I don't know how ssh2 works. I changed the connection to ssh2, but maybe those function doesn't works in a ssh server, I don't know...
My code:
$ftpuser = '***';
$ftppass = '***';
$dir = 'files/someFolder/';
$connection = ssh2_connect('**.***.***.***',22);
if(!$connection) {
error_log("Couldn't connect to $ftp_server");
exit;
}
$login_result = ssh2_auth_password($connection, $ftpuser, $ftppass);
ftp_chdir($connection, $dir);
$folders_files = ftp_nlist($connection, '.');
foreach ($folders_files as $folder_file) {
ftp_delete($connection, $folder_file);
}
ftp_rmdir($connection, $dir);
There are some errors:
PHP Warning: ftp_chdir(): supplied resource is not a valid FTP Buffer resource in...
PHP Warning: ftp_nlist(): supplied resource is not a valid FTP Buffer resource in...
PHP Warning: Invalid argument supplied for foreach() in...
PHP Warning: ftp_rmdir(): supplied resource is not a valid FTP Buffer resource in...
What the hell is going on here?
You're mixing the ssh2_* functions and the ftp_* functions. They're not interchangeable.
That said I'd recommend using phpseclib, a pure PHP SFTP implementation. An example:
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
$sftp->delete('dirname.remote', true); // deletes a directory and all its contents
?>
The fact that it can recursively delete stuff should be particularly useful to you. ie. if files/someFolder/ contains a folder A that itself contains another folder, folder B, you probably won't be able to delete it with your method whereas with phpseclib's deletion approach can delete it.
You must be inside a non-existent directory.
This code will help you understand what you are doing wrong.
echo "Current directory: " . ftp_pwd($connection) . "\n";
// try to change the directory to somedir
if (ftp_chdir($connection, "files/someFolder/")) {
echo "Current directory is now: " . ftp_pwd($connection) . "\n";
} else {
echo "Couldn't change directory\n";
}

Categories