我正在使用phpseclib,我正在尝试使用RSA密钥登录:
$ssh = new SSH2('<server_domain_name>');
$key = new RSA();
$key->load(file_get_contents('<private_key_path>'));
if($ssh->login('root',$key)){
echo "Logged In!!!";
} else {
echo "Login failed!";
}
但是登录失败!查看SSH2类内部,我可以看到使用RSA密钥登录发生在_login_helper()函数中(如果我错了,则正确),该函数由login()函数调用的_login()函数调用(在特定情况下)。
login() -> _login() -> _login_helper()
但是这段代码:
if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
if (!$this->_connect()) {
return false;
}
}
_login()函数中的总是返回false,因此执行永远不会到达_login_helper()函数。上述代码部分返回false的原因是这些变量/常量的默认值:
var $bitmap = 0;
const MASK_CONNECTED = 0x00000002;
我有点沮丧。我错过什么了吗?
编辑:我忘了说登录返回/失败后几秒钟。在_connect()方法中添加一些echo,我可以看到该方法在等待服务器数据时超时。在循环执行过程中:
while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(d.d+).*)#ms', $data, $matches))
服务器只输出一行表示"SSH-2.0-OpenSSH_4.3",然后(第二次执行循环)它在这里超时:
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
EDIT 2:我试图连接的一侧的SSH日志说:
连接被THE_SSH_SERVER_IP关闭
Nov 4 23:09:58 web1 sshd[10316]: Did not receive identification string fromTHE_ WEB_SERVER_IP
phpseclib在发送自己的服务器标识字符串之前读取服务器的服务器标识字符串。这就是PuTTY的作用。这里有一个示例日志文件,当我尝试连接到localhost:4022:
时Event Log: Writing new session log (SSH packets mode) to file: putty.log
Event Log: Looking up host "127.0.0.1"
Event Log: Connecting to 127.0.0.1 port 4022
Event Log: Server version: SSH-2.0-OpenSSH_6.6p1 Ubuntu-2ubuntu1
Event Log: Using SSH protocol version 2
Event Log: We claim version: SSH-2.0-PuTTY_Release_0.63
SSH规范如下:
When the connection has been established, both sides MUST send an
identification string. This identification string MUST be
SSH-protoversion-softwareversion SP comments CR LF
来源:https://www.rfc-editor.org/rfc/rfc4253部分- 4.2
请注意,它并没有说一方必须在另一方之前发送。双方都应该有可立即检索的内容。如果您的SSH服务器只是在客户端发送了它的标识字符串之后才有条件地使内容可用于检索,那么您的SSH服务器就有问题了。让我知道你使用的是哪个服务器,我会打开一个bug报告。
同时这里有一个修改版本的phpseclib,它先发送标识字符串而不是先读取它:
https://github.com/terrafrost/phpseclib/tree/send-identifier-first让我知道这是否适合你。让我知道你用什么作为你的服务器