phpseclib
PHP has an SSH2 library which provides access to resources (shell, remote exec, tunneling, file transfer) on a remote machine using a secure cryptographic transport. Objectively, it is a tedious and highly frustrating task for a developer to implement it due to its overwhelming configuration options and complex API with little documentation.
PHP具有SSH2库,该库可使用安全的密码传输方式访问远程计算机上的资源(shell,远程执行程序,隧道,文件传输)。 客观地讲,由于其繁琐的配置选项和复杂的API(几乎没有文档),对于开发人员而言,实现它是一项繁琐且令人沮丧的任务。
The phpseclib (PHP Secure Communications Library) package has a developer friendly API. It uses some optional PHP extensions if they’re available and falls back on an internal PHP implementation otherwise. To use this package, you don’t need any non-default PHP extensions installed.
所述phpseclib (PHP 小号 ecureÇommunications 库郭宝宏)封装具有显影剂友好API。 如果可用,它将使用一些可选PHP扩展,否则将依赖内部PHP实现。 要使用此软件包,您不需要安装任何非默认PHP扩展。
This will install the most recent stable version of the library via Composer.
这将通过Composer安装该库的最新稳定版本。
Before diving in blindly, I’d like to list some use-cases appropriate for using this library:
在盲目潜水之前,我想列出一些适合使用此库的用例:
Executing deployment scripts on a remote server 在远程服务器上执行部署脚本 Downloading and uploading files via SFTP 通过SFTP下载和上传文件 Generating SSH keys dynamically in an application 在应用程序中动态生成SSH密钥 Displaying live output for remote commands executed on a server 显示服务器上执行的远程命令的实时输出 Testing an SSH or SFTP connection 测试SSH或SFTP连接Using phpseclib, you can connect to your remote server with any of the following authentication methods:
使用phpseclib ,您可以使用以下任何一种身份验证方法连接到远程服务器:
RSA key RSA密钥 Password Protected RSA key 受密码保护的RSA密钥Username and Password (Not recommended)
用户名和密码( 不推荐 )
We will assume that you have a secure RSA key already generated. If you are not familiar with generating a secure RSA key pair, you can go through this article. For a video explanation, you can refer to Creating and Using SSH Keys from Servers For Hackers.
我们将假定您已经生成了一个安全的RSA密钥。 如果您不熟悉生成安全的RSA密钥对,则可以阅读本文 。 有关视频的说明,请参阅从“黑客服务器” 创建和使用SSH密钥 。
To log in to a remote server using RSA key authentication:
要使用RSA密钥认证登录到远程服务器:
namespace App; use phpseclib\Crypt\RSA; use phpseclib\Net\SSH2; $key = new RSA(); $key->loadKey(file_get_contents('privatekey')); //Remote server's ip address or hostname $ssh = new SSH2('192.168.0.1'); if (!$ssh->login('username', $key)) { exit('Login Failed'); }If your RSA keys are password protected, do not worry. Phpseclib takes care of this particular use case:
如果您的RSA密钥受密码保护,请不要担心。 Phpseclib处理这个特殊的用例:
namespace App; use phpseclib\Crypt\RSA; use phpseclib\Net\SSH2; $key = new RSA(); $key->setPassword('your-secure-password'); $key->loadKey(file_get_contents('privatekey')); //Remote server's ip address or hostname $ssh = new SSH2('192.168.0.1'); if (!$ssh->login('username', $key)) { exit('Login Failed'); }Alternatively, to log in to your remote server using a username and password (we don’t recommend this practice):
或者,要使用用户名和密码登录到远程服务器(我们不建议您这样做):
namespace App; use phpseclib\Net\SSH2; //Remote server's ip address or hostname $ssh = new SSH2('192.168.0.1'); if (!$ssh->login('username', 'password')) { exit('Login Failed'); }For other options such as No Authentication or Multi-Factor authentication please refer to the documentation
有关其他选项,例如“无身份验证”或“多重身份验证”,请参阅文档
The code to execute commands on a remote server is pretty simple. You call the $ssh->exec($cmd) method with the command to execute as the parameter.
在远程服务器上执行命令的代码非常简单。 您可以使用命令调用$ssh->exec($cmd)方法以将其作为参数执行。
namespace App; use phpseclib\Crypt\RSA; use phpseclib\Net\SSH2; $key = new RSA(); $key->loadKey(file_get_contents('privatekey')); //Remote server's ip address or hostname $ssh = new SSH2('192.168.0.1'); if (!$ssh->login('username', $key)) { exit('Login Failed'); } $ssh->exec('ls -la');In real life applications, we rarely execute a single command. We often need to traverse around the server using cd and execute many other commands. If you try to execute multiple commands on the remote server as below, it won’t give you the desired output:
在实际应用中,我们很少执行单个命令。 我们经常需要使用cd遍历服务器并执行许多其他命令。 如果您尝试按如下所示在远程服务器上执行多个命令,它将不会为您提供所需的输出:
$ssh->exec('pwd'); //outputs /home/username $ssh->exec('cd mysite.com'); $ssh->exec('pwd'); //outputs /home/usernameThe reason for above is that a call to the exec method does not carry state forward to the next exec call. To execute multiple commands without losing state:
上面的原因是对exec方法的调用不会将状态传递给下一个exec调用。 要执行多个命令而不丢失状态:
$ssh->exec('cd /home/username; ls -la'); //Lists all files at /home/usernameYou can append as many commands as you wish with a semicolon or new line character PHP_EOL.
您可以使用分号或换行符PHP_EOL 。
For example, if you want to run a full deployment script for Laravel:
例如,如果您想为Laravel运行完整的部署脚本:
$ssh->exec( "git pull origin master" . PHP_EOL . "composer install --no-interaction --no-dev --prefer-dist" . PHP_EOL . "composer dump-autoload -o" . PHP_EOL . "php artisan optimize" . PHP_EOL . "php artisan migrate --force" );In the above script, the whole set of commands is executed as a single shell script. Every command will be executed, even if some of them fail, just like in a regular shell script. As a default, this is fine, but if we need to exit on the first error, we have to alter our bash script. This is not something specific to phpseclib, it is related to bash scripting.
在上面的脚本中,整个命令集作为单个shell脚本执行。 每个命令都会执行,即使其中一些失败也会像常规的shell脚本一样执行。 默认情况下,这很好,但是如果需要在第一个错误时退出,则必须更改bash脚本。 这不是特定于phpseclib的东西,它与bash脚本相关。
If you put a set -e option at the beginning of the script, the script will terminate as soon as any command in the chain returns a non-zero value.
如果在脚本的开头放置set -e选项,则该脚本将在链中的任何命令返回非零值后立即终止。
For example, the modified version of the above deployment script would be
例如,上述部署脚本的修改后的版本为
$ssh->exec( "set -e" . PHP_EOL . "git pull origin master" . PHP_EOL . "composer install --no-interaction --no-dev --prefer-dist" . PHP_EOL . "composer dump-autoload -o" . PHP_EOL . "php artisan optimize" . PHP_EOL . "php artisan migrate --force" );The above script will terminate if any of the commands results in an error.
如果任何命令导致错误,以上脚本将终止。
The exec method returns the output of your remote script:
exec方法返回远程脚本的输出:
$output = $ssh->exec('ls -la'); echo $output;Sometimes, however, it does not return the whole output. You can overcome this by passing a closure as a second argument to the exec method to make sure that any uncaught output will also be returned.
但是,有时它不会返回整个输出。 您可以通过将闭包作为第二个参数传递给exec方法来克服此问题,以确保还返回任何未捕获的输出。
$ssh->exec( $deployment_script, function ($str) { $output .= $str; }); echo $output;Note: Error output, if any, will also be returned by the exec method or the underlying closure.
注意:错误输出(如果有)也将由exec方法或基础闭包返回。
If you want to execute the script via console commands and display live output, you can achieve this by echoing the output in the underlying closure.
如果要通过控制台命令执行脚本并显示实时输出,可以通过在基础闭包中回显输出来实现。
$ssh->exec($deployment_script, function ($str) { echo $str; });If you want to display it in a web browser, you need to flush (send) the output buffer with ob_flush().
如果要在Web浏览器中显示它,则需要使用ob_flush()刷新(发送)输出缓冲区。
$ssh->exec( $deployment_script, function ($str) { echo $str; flush(); ob_flush(); });It’s also possible to set many other available configuration options. You can call them as $ssh->{option}.
还可以设置许多其他可用的配置选项。 您可以将它们称为$ssh->{option} 。
For example: $ssh->setTimeout(100).
例如: $ssh->setTimeout(100) 。
All the options we haven’t covered yet are in the table below:
下表中尚未涵盖所有选项:
OptionUse casesetTimeout($seconds)$ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it’ll timeout. Setting $timeout to false or 0 will mean there is no timeout.write($cmd)Inputs a command into an interactive shell.read()Returns the output of an interactive shellisTimeout()Return true if the result of the last $ssh->read() or $ssh->exec() was due to a timeout. Otherwise it will return false.isConnected()Returns true if the connection is still activeenableQuietMode()Suppresses stderr so no errors are returneddisableQuietMode()Includes stderr in outputisQuiteModeEnabled()Returns true if quiet mode is enabledenablePTY()Enable request-pty when using exec()disablePty()Disable request-pty when using exec()isPTYEnabled()Returns true if request-pty is enabledgetLog()Returns a log of the packets that have been sent and received.getServerPublicHostKey()Returns the server public host key. Returns false if the server signature is not signed correctly with the public host key.getExitStatus()Returns the exit status of an SSH command or false.getLanguagesClient2Server()Return a list of the languages the server supports, when receiving stuff from the client.getLanguagesServer2Client()Return a list of the languages the server supports, when sending stuff to the client.getCompressionAlgorithmsServer2Client()Return a list of the compression algorithms the server supports, when sending stuff to the client.getCompressionAlgorithmsClient2Server()Return a list of the compression algorithms the server supports, when receiving stuff from the client.getMACAlgorithmsServer2Client()Return a list of the MAC algorithms the server supports, when sending stuff to the client.getMACAlgorithmsClient2Server()Return a list of the MAC algorithms the server supports, when receiving stuff from the client.getEncryptionAlgorithmsServer2Client()Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.getEncryptionAlgorithmsClient2Server()Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.getServerHostKeyAlgorithms()Return a list of the host key (public key) algorithms the server supports.getKexAlgorithms()Return a list of the key exchange algorithms the server supports. 选项 用例 setTimeout($seconds) $ssh->exec('ping 127.0.0.1'); 在Linux主机上将永远不会返回并且将无限期运行。 setTimeout()使它超时。 将$timeout设置$timeout false或0表示没有超时。 write($cmd) 将命令输入到交互式外壳中。 read() 返回交互式shell的输出 isTimeout() 如果最后的$ssh->read()或$ssh->exec()结果是由于超时而返回的,则返回true。 否则它将返回false。 isConnected() 如果连接仍处于活动状态,则返回true enableQuietMode() 禁止stderr,因此不会返回任何错误 disableQuietMode() 在输出中包含stderr isQuiteModeEnabled() 如果启用了安静模式,则返回true enablePTY() 使用exec()时启用request-pty disablePty() 使用exec()时禁用request-pty isPTYEnabled() 如果启用了request-pty,则返回true getLog() 返回已发送和接收的数据包的日志。 getServerPublicHostKey() 返回服务器公共主机密钥。 如果未使用公共主机密钥正确签名服务器签名,则返回false。 getExitStatus() 返回SSH命令的退出状态或为false。 getLanguagesClient2Server() 从客户端接收内容时,返回服务器支持的语言列表。 getLanguagesServer2Client() 将内容发送到客户端时,返回服务器支持的语言列表。 getCompressionAlgorithmsServer2Client() 将内容发送到客户端时,返回服务器支持的压缩算法的列表。 getCompressionAlgorithmsClient2Server() 从客户端接收内容时,返回服务器支持的压缩算法的列表。 getMACAlgorithmsServer2Client() 将内容发送到客户端时,返回服务器支持的MAC算法列表。 getMACAlgorithmsClient2Server() 当从客户端接收消息时,返回服务器支持的MAC算法列表。 getEncryptionAlgorithmsServer2Client() 在将内容发送到客户端时,返回服务器支持的(对称密钥)加密算法的列表。 getEncryptionAlgorithmsClient2Server() 从客户端接收内容时,返回服务器支持的(对称密钥)加密算法的列表。 getServerHostKeyAlgorithms() 返回服务器支持的主机密钥(公共密钥)算法的列表。 getKexAlgorithms() 返回服务器支持的密钥交换算法的列表。LIBSSH2 – The SSH library – The library provides similar functionality, but is a little less intuitive to use, and it requires you to have libssh2 installed on the server, which most shared hosts don’t have.
LIBSSH2 – SSH库 –该库提供类似的功能,但使用起来不太直观,它要求您在服务器上安装libssh2 ,而大多数共享主机都没有。
Process component – Symfony’s component for writing your own script for connecting and executing commands – as you would do in a normal terminal. This limits us in the configuration options that we might need to set. Achieving the same functionality the above configuration methods provide us with with Process would require in-depth bash knowledge. If your use-case involves only running a local script, however, this might prove to be a useful component.
过程组件 – Symfony的组件,用于编写自己的脚本以连接和执行命令–与在普通终端中一样。 这限制了我们可能需要设置的配置选项。 要实现上述配置方法为Process提供的相同功能,需要深入的bash知识。 但是,如果您的用例仅涉及运行本地脚本,则可能证明这是一个有用的组件。
In this article, we introduced phpseclib, a package which provides an alternative for SSH2. We have covered the configuration options necessary to get started, and the table above should help you fill in the gaps and give an overview of other configuration options available to you.
在本文中,我们介绍了phpseclib ,这是一个可替代SSH2的软件包。 我们已经介绍了入门所需的配置选项,并且上表应帮助您填补空白,并概述您可以使用的其他配置选项。
For an in-depth implementation of key-based communication, see our previous tutorial.
有关基于密钥的通信的深入实现,请参阅我们以前的教程 。
How do you execute remote commands? Can you think of any advanced use cases for this library? What are they? Let us know in the comments!
您如何执行远程命令? 您能想到该库的任何高级用例吗? 这些是什么? 让我们在评论中知道!
翻译自: https://www.sitepoint.com/phpseclib-securely-communicating-with-remote-servers-via-php/
phpseclib
相关资源:phpseclibPHP安全通信库