0

I want to be able to get a file through SFTP from a server in order for my web server to allow users to download it afterwards. To achieve this, I am using the phpseclib library. Unfortunately, this is really slow as I can only achieve speeds of 300-350kb/s when I could achieve over 1mb/s before when directly downloading from the server hosting the original files. For some internal reasons in our company, we have to relocate these files on an other server which only has the port 22 opened, so when a user goes on the following link: http://my.website.com/some/path/getfile/getfile.php?filename=someFileName.extension my php script connects via SSH to the server that hosts the files, then downloads the specified file to the php://output stream for the user to download it.

Here is my php script:

error_reporting(E_ERROR);
include('Net/SFTP.php');
include('Crypt/RSA.php');

if (!isset($_GET['filename']))
    die();

# This if statement is there as a layer of protection to prevent users from going elsewhere
# in the filesystem of the server.
if (!strpos($_GET['filename'], '..') and !strpos($_GET['filename'], '/') and !strpos($_GET['filename'], '\\')) {
    $sftp = new Net_SFTP('my.website.com');
    $key = new Crypt_RSA();
    $key->loadkey(file_get_contents('key.pvt'));
    if (!$sftp->login('loginUserName', $key)) {
        exit('Login Failed');
    }

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.$_GET['filename']);
    header('Content-Transfer-Encoding: binary');
    header('Cache-Control: must-revalidate');
    header('Accept-Ranges: bytes');
    header('Expires: 0');
    header('Pragma: public');
    header('Content-Length: ' . $sftp->size('transfer/'.$_GET['filename']));
    ob_clean();
    flush();

    set_time_limit(3600);
    $sftp->get('transfer/'.$_GET['filename'], 'php://output');
}

This works, though as mentioned it is really slow. What could be causing this slow down?

Choub890
  • 1,163
  • 1
  • 13
  • 27
  • 1
    SFTP adds encryption, which incurs some performance penalty. Also consider that `phpseclib` is a "pure PHP implementation", which is always going to be slower than a native (C) implementation (like OpenSSL or [LibreSSL](http://www.libressl.org/)). – Jonathon Reinhart Jul 16 '14 at 17:40
  • @JonathonReinhart Would there be a way to specify to the function not to add encryption? Or, using the same library, could I use another file transfer method that does not use encryption? Information security for the kind of files being transferred is not very vital here. – Choub890 Jul 16 '14 at 17:43
  • There are plenty of other methods. HTTP and FTP come to mind. But I would suggest using a secure method with proper authentication regardless. – Jonathon Reinhart Jul 16 '14 at 17:46
  • @JonathonReinhart With the constraint of only having port 22 opened, would SFTP be the only way to fetch files on that server? – Choub890 Jul 16 '14 at 17:51
  • 1
    Both [SCP](http://en.wikipedia.org/wiki/Secure_copy) or [SFTP](http://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) run over SSH on port 22, and by nature include encryption. – Jonathon Reinhart Jul 16 '14 at 18:24

1 Answers1

1

phpseclib uses mcrypt if it's available and it's own pure PHP implementation otherwise. If you do phpinfo() do you see mcrypt installed?

Also, SSH2 supports a multitude of encryption algorithms and some are faster than others. It could be that the client you're comparing phpseclib against is simply using a faster algorithm than phpseclib has implemented.

Finally, what version of phpseclib are you using? The latest is 0.3.7.

neubert
  • 15,947
  • 24
  • 120
  • 212
  • The reason we use phpseclib is because the system admin of the server doesn't want us installing anything on there. Since phpseclib is portable (no need to install it, just need to include files when we want to use it), this is why we went with it. Would mcrypt really help speed-wise? If it does, it may give me the arguments I need to let the sys admin install it on the server. If we do install it, would there be any configurations required afterwards for phpseclib to use mcrypt instead of its own implementation? – Choub890 Jul 17 '14 at 14:45
  • 1
    With mcrypt disabled I get a speed marginally better than what's posted at http://phpseclib.sourceforge.net/crypt/examples.html - 0.84s for 1mb. With mcrypt it's 0.06 seconds. So even if phpseclib's pure PHP implementation is the fastest *pure PHP* implementation mcrypt still blows it out of the water. mcrypt is very widely deployed (much much more so than libssh2) and doesn't require any configuration. Just do sudo apt-get or sudo yum and it should work! Honestly, that you don't have mcrypt installed is a little surprising given how commonly it is installed lol – neubert Jul 17 '14 at 15:04