Cygwin OpenSSH 服务器在 PHP 发出第一个命令后没有响应(使用 phpseclib)

Cygwin OpenSSH server does not respond after first command from PHP (Using phpseclib)

我让 cygwin 和 sshd 工作正常。而且使用putty完全没有问题。即使对于多个命令,它也会按预期响应。但是当使用 phpseclib 时,只收到第一个命令的响应。随后的命令给出空白答复。 这是我要执行的脚本 -

<?php
include('Net/SSH2.php');
define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX);
$host = "XXXX";
$username = "XXXX"; 
$password = "XXXX"; 
$ssh = new Net_SSH2($host);
if (!$ssh->login($username, $password)) {
    exit('Login Failed');
}
echo $ssh->exec('nproc');
echo $ssh->exec('nproc');
echo $ssh->getLog();
?>

但是,创建新的 ssh 对象会给出响应。但是,我无法将同一个对象用于第二个 exec 请求。当目标是 centos 机器时,这工作正常。

这是 phpseclib 的日志输出- http://pastebin.com/ff3sfux7

这……很奇怪。 FWIW 它似乎不是 phpseclib 问题,而是服务器问题。如果您查看日志,您会看到两个 <- NET_SSH2_MSG_CHANNEL_EOF 数据包。 nproc 响应就在第一个之前 (<- NET_SSH2_MSG_CHANNEL_DATA),但第二个没有类似的响应。

您发出的每个 nproc 请求都会导致服务器最终发送 exit-status SSH_MSG_CHANNEL_REQUEST。这是您日志文件中的第一个:

<- NET_SSH2_MSG_CHANNEL_REQUEST (since last: 0.0839, network: 0.0838s)
00000000  00:00:00:00:00:00:00:0b:65:78:69:74:2d:73:74:61  ........exit-sta
00000010  74:75:73:00:00:00:00:00                          tus.....

这是您日志文件中的第二个

<- NET_SSH2_MSG_CHANNEL_REQUEST (since last: 0.0461, network: 0.046s)
00000000  00:00:00:00:00:00:00:0b:65:78:69:74:2d:73:74:61  ........exit-sta
00000010  74:75:73:00:00:00:00:ff                          tus.....

除了最后一个字节在第一个(好的)中是 00 而在第二个(坏的)中是 ff 之外,它们几乎完全相同。这是 SSH_MSG_CHANNEL_REQUEST 退出状态数据包的剖析:

  byte      SSH_MSG_CHANNEL_REQUEST
  uint32    recipient channel
  string    "exit-status"
  boolean   FALSE
  uint32    exit_status

所以基本上最后四个字节代表 255 的 uint32 exit_status。

引用 wikipedia's article on exit status,“退出状态介于 0 和 255 之间”。还有,

For the shell’s purposes, a command which exits with a zero exit status has succeeded. A non-zero exit status indicates failure.

所以当 运行 第二个命令时,您的 Linux 框出现了某种错误。

stderr (SSH_MSG_CHANNEL_EXTENDED_DATA) 上也没有任何输出,所以很难说发生了什么。

根据 http://tldp.org/LDP/abs/html/exitcodes.html,255 退出状态表示“退出状态超出范围”。 IE。 nproc 尝试执行 exit -1exit 256。无论哪种方式,听起来都像是 nproc 错误或其他问题。也许尝试确保您系统上的所有内容都是最新的?

我找到了解决方案 - 问题的原因是,在基于 windows 的系统中,setuid 在执行新命令之前被调用。对于第一个命令,它最初是设置的,所以没有问题。然而,随后的调用导致尝试重新分配它并且失败并且 openssh 将无法做到这一点。这已经在 ssh-host-config 脚本中解释过-

*** Info: You appear to be running Windows XP 64bit, Windows 2003 Server,
*** Info: or later.  On these systems, it's not possible to use the LocalSystem
*** Info: account for services that can change the user id without an
*** Info: explicit password (such as passwordless logins [e.g. public key
*** Info: authentication] via sshd).

*** Info: If you want to enable that functionality, it's required to create
*** Info: a new account with special privileges (unless a similar account
*** Info: already exists). This account is then used to run these special
*** Info: servers.

为了解决它,您需要创建脚本尝试创建的特权用户帐户,并确保在脚本末尾显示 -

*** Info: The sshd service has been installed under the 'cyg_server'
*** Info: account.  To start the service now, call `net start sshd' or
*** Info: `cygrunsrv -S sshd'.  Otherwise, it will start automatically
*** Info: after the next reboot.

任何指示未找到该帐户且默认为 "SYSTEM" 帐户的消息都会导致此问题。在这种情况下,请确保密码文件是最新的并包含新用户。

并且当您启动 Windows 服务管理器并检查 CYGWIN sshd 服务的属性时,在登录选项卡下它需要说明它正在使用新创建的特权帐户而不是本地帐户。

还要验证在组策略编辑器 -> 安全设置 -> 本地策略 -> 用户权限分配下,新用户帐户需要具有创建令牌对象并充当操作系统一部分的权限。