简体   繁体   English

PHPSeclib 公钥认证在本地主机上成功; 部署失败

[英]PHPSeclib Public Key Authentication Successful on Localhost; Failing when deployed

I've created a script which connects to a server using the phpseclib extension, using public key autentication (as you see here ), by generating a key pair using ssh-keygen .我创建了一个脚本,它使用phpseclib扩展连接到服务器,使用公钥身份验证(如您在此处看到的),通过使用ssh-keygen生成密钥对。

What I'm facing now is that the connection works very well when I run the php script from my localhost, but when I run the script from the server, I always get a failed login attempt, with the following error reported:我现在面临的是,当我从本地主机运行 php 脚本时,连接工作得很好,但是当我从服务器运行脚本时,我总是尝试登录失败,并报告以下错误:

SSH_MSG_USERAUTH_FAILURE

(which I get when using $sftp->getLastError() after trying $sftp->login() ). (我在尝试$sftp->login()后使用$sftp->getLastError()时得到的)。

Any idea why this happens?????知道为什么会这样吗????

UPDATE更新

Thought it may be due to some error related to file_get_contents(), so I've checked on it, it's the value of the key indeed.认为可能是由于一些与file_get_contents()相关的错误,所以我已经检查过了,确实是key的值。 I've also directly pasted the private key into the PublicKeyLoader::load() function, same error happened, so that's not the reason.我也直接将私钥粘贴到 PublicKeyLoader::load() 函数中,发生了同样的错误,所以这不是原因。

The main log events where I think the issue happened are, when running the exact same script trying to establish a connection to the target server:我认为发生问题的主要日志事件是,当运行完全相同的脚本尝试建立与目标服务器的连接时:

from the localhost (working):从本地主机(工作):

NET_SSH2_MSG_SERVICE_REQUEST;
NET_SSH2_MSG_SERVICE_ACCEPT;
NET_SSH2_MSG_USERAUTH_REQUEST (ssh-connection none); 
NET_SSH2_MSG_USERAUTH_FAILURE; 
NET_SSH2_MSG_USERAUTH_REQUEST(ssh-connection publickey); 
NET_SSH2_MSG_USERAUTH_PK_OK;

from the server (not working):从服务器(不工作):

NET_SSH2_MSG_SERVICE_REQUEST;
NET_SSH2_MSG_SERVICE_ACCEPT;
NET_SSH2_MSG_USERAUTH_REQUEST (ssh-connection none); 
NET_SSH2_MSG_USERAUTH_FAILURE;
NET_SSH2_MSG_USERAUTH_REQUEST (ssh-connection publickey); 
NET_SSH2_MSG_USERAUTH_FAILURE;

I generated three key pairs, ran the localhost and the server-client test with all of them, and I always get what's shown above.我生成了三个密钥对,对所有这些都运行了本地主机和服务器-客户端测试,我总是得到上面显示的内容。 And when I echo it out, I definitely get the key, and don't worry it's not an ecrypted OpenSSH private key, that's not the reason (not supported in phpseclib ), and that would then fail on the localhost too (which I've tested).当我回应它时,我肯定得到了密钥,不用担心它不是一个 ecrypted OpenSSH 私钥,这不是原因(在phpseclib不支持),然后在本地主机上也会失败(我'我测试过)。

So looks like it's failing on the step of the public key authentication on the server, although I'm using the exact same script, and although I'm getting the exactly correct key when echoing the retrieved key out, also on the server-side.所以看起来它在服务器上的公钥身份验证步骤中失败了,尽管我使用的是完全相同的脚本,并且虽然在回显检索到的密钥时我得到了完全正确的密钥,也在服务器端.

I've then checked what happens if I change a single character of my key;然后我检查了如果我更改了密钥的单个字符会发生什么; if that reproduces the above-displayed SSH - log, but no.如果这重现了上面显示的 SSH - 日志,但没有。 If I do so, the script interrupts before logging anything, throwing an phpseclib3\\Exception\\NoKeyLoadedException: Unable to read key Exception.如果我这样做,脚本会在记录任何内容之前中断,抛出一个phpseclib3\\Exception\\NoKeyLoadedException: Unable to read key Exception。

From this I concluded that the only problem could be that the key is encoded in a certain wrong way before being sent to the server, and that the server misunderstands the key due to that.由此我得出结论,唯一的问题可能是密钥在发送到服务器之前以某种错误的方式编码,并且服务器因此误解了密钥。

Considering this, I've found that phpseclib requires the paragonie package according to this , and that one of phpseclibs dependencies of paragonie do some base64 - encoding.考虑到这一点,我发现phpseclib要求paragonie根据包装,和一个phpseclibs的依赖paragonie做一些的base64 -编码。 I thus supposed that it may the case that the encoding used to send the key is not properly done for some reason, and went to check on how the phpseclib extension was installed on the server (done by server admins, not by me).因此,我认为可能是由于某种原因用于发送密钥的编码没有正确完成,并检查了phpseclib扩展是如何安装在服务器上的(由服务器管理员完成,而不是由我完成)。

Turned out it is a plesk server, which requires you to upload new composer packages in a somewhat unusual way, namely via the composer.json file, according to this .原来它是一个 plesk 服务器,它要求您以一种有点不寻常的方式上传新的 Composer 包,即通过composer.json文件,根据这个 I've only installed composer packages either via command prompt, via SSH directly on the server, or to a local environment + deployed on the server.我只通过命令提示符、直接在服务器上通过 SSH 安装了 Composer 包,或者安装到本地环境 + 部署在服务器上。 Neither of this work, and the instruction above also did not work.这两项都不起作用,上面的说明也不起作用。

I've then checked the composer.json file, and found its content to be:然后我检查了composer.json文件,发现它的内容是:

{ 
  "name": "packagex/packagex", 
  "type": "plugin", 
  "description": "secret_description", 
  "keywords": ["secret_keyword"], 
  "homepage": "secret_url", 
  "license": "secret_license", 
  "authors": [ { "name": "secret_name", "email": "secret_mail" } ],
  "require": 
    {
      "php": ">=5.3", 
      "phpseclib/phpseclib": "^3.0"
    }
}

The file contained an extension already, which we cannot touch, but we need to add phpseclib .该文件已经包含一个我们无法触及的扩展名,但我们需要添加phpseclib To do so, the line "phpseclib/phpseclib": "^3.0" has simply been added into the require key of the JSON, but I feel that this is not the correct way.为此,行"phpseclib/phpseclib": "^3.0"已简单地添加到 JSON 的require键中,但我觉得这不是正确的方法。 IMHO, this kind of interpretes the phpseclib as a dependency of the already used package, which are completely independent from each other.恕我直言,这种将phpseclib解释为已经使用的包的依赖项,它们彼此完全独立。

I'm starting to think now that this may be the final reason why the script fails when run on the server-side: the package is not properly installed in terms of its dependencies, hence the dependencies phpseclib itself needs are not properly used, as the phpseclib package itself is listed as a dependency.我现在开始认为这可能是脚本在服务器端运行时失败的最终原因:包的依赖项没有正确安装,因此没有正确使用phpseclib本身需要的依赖phpseclib ,如phpseclib包本身被列为依赖项。 Due to this, some missing base64-encoding or similar ( paragonie dependency of phpseclib package, see above) may be causing the issue.由于这一点,一些的base64编码或类似的(缺少paragonie的依赖phpseclib包,见上文)可能会导致问题。 Is this possible?这可能吗? To eliminate this reason;消除这个原因; I'd need to know how to properly install an extension via composer via composer.json on a plesk server, without touching the previously in-this-way installed packages.我需要知道如何在 plesk 服务器上通过 composer.json 通过composer.json正确安装扩展,而无需触及之前以这种方式安装的软件包。 Any idea on how to do that?关于如何做到这一点的任何想法? I've also posted a separate question for this, for further details;我还为此发布了一个单独的问题,以获取更多详细信息; you may check on it .你可以检查一下

What's also maybe causing an issue is that the current composer.json file requires a php version below the one which is required atm by phpseclib (php: >=5.6.1).也可能导致问题的是,当前的composer.json文件需要低于phpseclib所需的 php 版本(php:> = 5.6.1)。 But again, to change this, I need to know how to modify the composer.json file in the proper way.但同样,要改变这一点,我需要知道如何以正确的方式修改composer.json文件。

UPDATE更新

I've updated the composer.json file by copying its contents from the plesk server to a local environment where I downloaded the composer.我通过将内容从 plesk 服务器复制到我下载 Composer 的本地环境来更新composer.json文件。 There I then installed the phpseclib package via command prompt, and then copied the resulting composer.json back to the Plesk Server.然后我通过命令提示符安装了phpseclib包,然后将生成的composer.json复制回 Plesk 服务器。 And I get exactly the same issue again (and besides also the same composer.json content as before).而且我再次遇到完全相同的问题(此外还有与以前相同的composer.json内容)。 Help..?帮助..?

Okay so no clue why exactly this was the solution, but I definitely found it out by doing some checkups exclusively on the target server's side.好的,所以不知道为什么这是解决方案,但我确实通过在目标服务器端进行了一些检查来确定它。 That's why I would like to attribute this bounty to @neubert, how can I actually do that?这就是为什么我想将此赏金归功于@neubert,我该怎么做?

So what happened is that I've checked (among blocked IPs etc) on the target server on which port it listens for SFTP connections.所以发生的事情是我已经在目标服务器上检查(在被阻止的 IP 等中)它在哪个端口上侦听 SFTP 连接。 And I noticed that it A) was not listening at the standard port and B) blocked incoming connection requests on the standard port.我注意到它 A) 没有在标准端口上侦听,B) 阻止了标准端口上的传入连接请求。

Weirdly, when run from the local machine, the SSH connection could be established without any problem at all, without specifying any port, hence using the standard port, all the time.奇怪的是,当从本地机器运行时,可以毫无问题地建立 SSH 连接,无需指定任何端口,因此一直使用标准端口。

In the script deployed on the server, the SSH connection could exclusively be established if the connection request was made on the port the server was configured to listen for SFTP.在部署在服务器上的脚本中,如果在服务器配置为侦听 SFTP 的端口上发出连接请求,则可以专门建立 SSH 连接。

Even more interestingly, the script run on the localhost fails in the way the deployed script failed when I specify the non-standard port in it.更有趣的是,当我在其中指定非标准端口时,在本地主机上运行的脚本会以部署脚本失败的方式失败。

So in the end, no idea why this happens, but it's definitely all confirmed with tests.所以最后,不知道为什么会发生这种情况,但这肯定是通过测试证实的。 If anyone can explain this, I'm really deeply interested!如果有人可以解释这一点,我真的很感兴趣! But again, ur comments helped me to focus on the target server for an entire afternoon, so thx a lot!但同样,你的评论帮助我将整个下午的注意力集中在目标服务器上,所以非常感谢!

And PS to the downvoters of this imho really interesting issue: think again :)和这个恕我直言非常有趣的问题的downvoters PS:再想一想:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM