如何在PHP中安全地维护持久的SSH连接?

时间:2013-01-23 07:53:53

标签: php security ssh

我目前正在使用一个使用主从模型的VPS面板。一个主服务器运行用PHP编写的面板,并通过SSH管理多个从服务器。从属服务器通过有限帐户访问,可以使用特定服务器管理相关命令,并且所有交互都记录在帐户本身无权访问的目录中。

我目前正在使用PHP-SSH2,但这种方法存在一些问题:

  • 不能可靠地返回退出代码,因此所有命令都必须在包装器脚本中执行,该脚本将stdout,stderr和退出代码打包成JSON对象并通过stdout返回。此脚本必须存在于每个从属服务器上。
  • PHP-SSH2库不知道“自定义连接超时”的概念,这意味着我必须在尝试使用PHP-SSH2连接之前使用fsockopen探测服务器 - 如果我不这样做,无法访问的服务器可能会延迟一分钟或更长时间的页面加载。由于下一期问题,情况会更糟。
  • 无法建立持久连接。这会在面板中导致绝对荒谬的页面加载时间,尤其是与之前的超时问题相结合。

现在,我正在努力解决最后一个问题。

我遇到过几种可能的解决方案,但它们都存在某种问题:

  • 使用PHPSecLib,一个纯PHP SSH实现,并用pfsockopen调用替换所有fsockopen调用。这将使连接持久化,但它比我想要的更黑,并且PHP中持久套接字的安全含义还不清楚。
  • 设置从主服务器到每个从属服务器的持久SSH隧道,并在每个从属服务器上运行一个简单的守护进程(绑定到localhost),该服务器运行它所告知的任何内容。出于两个原因,这是一个问题。首先,它介绍了在从服务器上需要一个守护进程,这是我宁愿避免的。第二个问题是,如果有人要破坏从属服务器上的有限帐户,他们仍然可以通过连接到“命令守护进程”来运行某些系统命令,即使他们无法从自己的shell访问这些命令。这是一个问题。
  • 在主服务器上运行守护程序,该守护程序代表面板管理与从属服务器的持久SSH连接。这将涉及用Python编写SSH客户端(这是我熟悉的唯一合适的语言),并且可能归结为使用paramiko。由于paramiko的文档很差,这不是一个非常有吸引力的选项,甚至可能导致安全问题,因为我并不完全清楚如何在paramiko中使用假设

以下不是一个选项:

  • 切换到面板本身的其他语言。我正在用PHP编写面板,因为这是我最熟悉的语言,而且我知道我可能会遇到的怪癖和潜在问题。用我不熟悉的语言写这样一个重要的面向公众的项目是一个坏主意。
  • 使用Twisted作为第三个“可能的解决方案”。 Twisted是一个非常大且复杂的依赖,文档似乎比paramiko更差。
  • 在从属服务器上运行HTTPd或其他非SSH面向公众的守护程序。

实际上,当有多个服务器需要联系页面加载时,我看到有时超过一分钟的页面加载时间。对于VPS面板来说,这显然是不可接受的。

我的目标是使用某种实现来避免使用PHP-SSH2时引入的连接开销。以安全的方式执行此操作的最佳方法是什么,同时在从属服务器上引入最少量的依赖项?

2 个答案:

答案 0 :(得分:1)

您可以使用autossh,并使用autossh创建反向(portforward)隧道。然后让你的php应用程序与那些反向ssh端口对话。如果ssh连接失败,autossh将继续尝试重新创建连接。你的php应用程序将无法连接到反向隧道,甚至没有超时。

答案 1 :(得分:0)

选项3如何,但也在PHP中编写守护进程?这就是我尝试使用自己的类似项目的路线。

您可以使用FIFO文件而不是套接字与其进行通信。