我正在尝试通过SSH从PHP脚本在远程服务器上运行命令。这是片段:
$ssh_command = "ssh -F keys/config -o UserKnownHostsFile=keys/known_hosts -i keys/deployment_key -p $ssh_port $r
$git_fetch = "git --git-dir=$remote_path/.git --work-tree=$remote_path fetch 2>&1";
exec("$ssh_command '$git_fetch' 2>&1", $out);
如果我从命令行运行脚本,该脚本运行正常,因为它以具有常规登录shell和他们自己的.ssh目录的用户身份运行。当我尝试通过Web界面运行脚本时,它会失败,因为SSH无法在Apache用户的主目录中创建其.ssh目录。
是否可以在没有.ssh目录的情况下使用SSH,或者是否有另一种方法可以作为Apache用户运行SSH?我不想为Apache用户创建一个.ssh文件夹。
答案 0 :(得分:3)
我能够通过一个小问题/副作用解决这个限制。
设置选项UserKnownHostsFile=/dev/null
和StrictHostKeyChecking=no
,您可以欺骗SSH,而不是实际存储或要求验证主机密钥。
将StrictHostKeyChecking
设置为no允许在未事先知道或验证其密钥的情况下连接到服务器;并且/dev/null
使用UserKnownHostsFile
只读取和写入任何内容,因此不会读取已保存的值。
需要注意的是,SSH仍然会尝试创建.ssh
目录并失败,但失败会导致警告并继续连接。警告将包含在您的输出中(除非您要禁止警告)。
这是一个例子。注意:对于此示例,我没有设置任何身份验证,因此它将尝试使用密码身份验证并失败,但由于您使用的是身份,因此您应该可以正常连接。
<?php
$ssh_command = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "
."-p 2223 user@host.localdomain";
exec("$ssh_command ls 2>&1", $out);
var_dump($out);
// output when called from browser running as daemon(1)
array(5) {
[0]=>
string(44) "Could not create directory '/usr/sbin/.ssh'."
[1]=>
string(110) "Warning: Permanently added '[host.localdomain]:2223,[192.168.88.20]:2223' (RSA) to the list of known hosts."
[2]=>
string(36) "Permission denied, please try again."
[3]=>
string(36) "Permission denied, please try again."
[4]=>
string(82) "Received disconnect from 192.168.88.20: 2: Too many authentication failures for user"
}
您的输出很可能只包含关于无法创建.ssh
目录的第一个警告,然后是关于将主机永久添加到已知主机列表(/dev/null
)的警告,然后是你命令的输出;所以你必须检查第一行是否是这个警告,并将其从$out
数组中移出。
另一个注意事项:这确实打开了中间人攻击或DNS / IP黑客的可能性,让你尝试连接到流氓服务器。
请参阅Symantec的SSH Host Key Protection上的这篇文章。
答案 1 :(得分:3)
我会使用phpseclib, a pure PHP SSH implementation:
<?php
include('Net/SSH2.php');
$key = new Crypt_RSA();
//$key->setPassword('whatever');
$key->loadKey(file_get_contents('privatekey'));
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', $key)) {
exit('Login Failed');
}
echo $ssh->read('username@username:~$');
$ssh->write("ls -la\n");
echo $ssh->read('username@username:~$');
?>
当我们说PHP SSH库是PECL扩展时,我可以想象的另一件事。我个人建议不要使用它,因为它的编写非常糟糕。除了它之外,它很难安装并且支持不当需要您提供公钥和私钥。 phpseclib只需要私钥。这是有道理的,因为私钥通常包含嵌入其中的公钥。 PECL SSH2扩展需要单独提取,这很愚蠢。
phpseclib还支持比PECL SSH2库更多的格式。 phpseclib支持PuTTY密钥格式,XML签名密钥等。
答案 2 :(得分:0)
不,在使用OpenSSH客户端时,您需要在用户家中使用.ssh。没有办法避免这种情况 - 它本身就是一个安全功能,因为它包含整体设置。只需保留一个空的虚拟目录 - 客户端不会在那里写 - 但是你需要有足够的用户权限。
答案 3 :(得分:0)
解决方案:
不要这样做。我多年没有使用过PHP,但在任何现代的通用编程语言中,这都是一个巨大的WTF。我注意到有一个用户想要使用PHP SSH2库...这将是你要走的路,恕我直言。
只有当您产生副作用且结果无关紧要时,才会跳出shell来执行命令。如果您依赖于此任何重要的事情,或者命令的结果应该以任何方式修改程序状态,您需要找到一个内部库来处理这个问题,或者扩展语言以通过适当的C库。否则,你就会为自己创造一个受伤的世界。
答案 4 :(得分:0)
问题是SSH寻找的第一件事是用户的配置文件。您可以使用 -F 标志来指定您自己的配置文件的位置,这应该可以解决问题,虽然我现在急着工作,所以我没有仔细检查这个。您需要指定其他内容的位置,例如身份文件,&amp; c。,其中。该文件需要具有正确的所有权和权限,否则SSH会抱怨。
也就是说,使用像SSH2这样的SSH库是一个非常优秀的解决方案,如果可能的话,它就会被淘汰出局。
答案 5 :(得分:0)
您可以使用HOME环境变量控制〜/ .ssh将落在哪里。这样你可以确定它不会是Apache服务的目录。