使用PHP的SSH连接

使用PHP的SSH连接,php,linux,ssh,Php,Linux,Ssh,我目前正在进行一个项目,用PHP对系统进行更改(例如更改Nginx/restarting services的配置文件) PHP脚本正在本地主机上运行。在我看来,最好的(阅读:最安全的)方法是使用SSH建立连接。我正在考虑下列选择之一: 选项1:在php会话中存储用户名/密码并提示输入sudo 使用带有用户名/密码的phpseclib,将这些值保存在php会话中,并为每个命令提示sudo 选项2:使用root登录 在登录脚本中使用根用户名和密码的phpseclib。在这种情况下,您不必向用户询问s

我目前正在进行一个项目,用PHP对系统进行更改(例如更改Nginx/restarting services的配置文件)

PHP脚本正在本地主机上运行。在我看来,最好的(阅读:最安全的)方法是使用SSH建立连接。我正在考虑下列选择之一:

选项1:在php会话中存储用户名/密码并提示输入sudo

使用带有用户名/密码的phpseclib,将这些值保存在php会话中,并为每个命令提示sudo

选项2:使用root登录

在登录脚本中使用根用户名和密码的phpseclib。在这种情况下,您不必向用户询问sudo。(并非真正安全的解决方案)


选项3:使用从文件读取的公钥进行身份验证

使用带有公钥的PHP SSHlib进行身份验证,并将公钥放在www根目录之外

<?php

    $connection = ssh2_connect('shell.example.com', 22, array('hostkey' => 'ssh-rsa'));
    if (ssh2_auth_pubkey_file($connection, 'username', '/home/username/.ssh/id_rsa.pub', '/home/username/.ssh/id_rsa', 'secret')) {
        echo "Public Key Authentication Successful\n";
    } else {
        die('Public Key Authentication Failed');
    }
?>


选项4:?

如果您在同一台主机上运行,我建议您直接编写配置文件并(重新)启动服务,或者编写包装器脚本

第一个选项显然需要非常高的特权级别,我不建议这样做。然而,它将是最容易实现的。您使用ssh的其他命名选项没有多大帮助,因为可能的攻击者仍然可以轻松获得根权限


第二种选择更安全,包括编写具有高级访问权限的程序,该程序只获取指定的输入文件,例如从目录中获取。php脚本只是用户的前端,将编写所述输入文件,因此只需要非常低的权限。这样,您就可以将高权限和低权限分开,从而降低风险,因为保护程序更容易,可能的攻击者只能通过文本文件间接地使用该程序。此选项需要更多的工作,但更安全。

您可以扩展选项3并在不使用任何库的情况下使用SSH密钥

$command = sprintf('ssh -i%s -o "StrictHostKeyChecking no" %s@%s "%s"',
                $path, $this->getUsername(), $this->getAddress(), $cmd );
return shell_exec( $command );
我在我的项目中经常使用它。你可以看看我创造的

上面的问题是,您无法做出实时决策(连接到服务器时)。如果您需要实时,请尝试调用PHP扩展


我同意你的看法。SSH接缝被认为是最安全的选项。

我建议您通过3个简单的步骤来实现这一点:

首先。 创建另一个用户(例如
runner
),并使您的敏感数据(如用户/通行证、私钥等)仅可供该用户访问。换句话说,拒绝php代码访问这些数据

秒。 之后,创建一个简单的阻塞fifo管道,并向php用户授予写访问权

最后一个。 最后编写一个简单的守护进程,从fifo读取行,并通过ssh命令执行。使用
runner
user运行此守护程序

要执行命令,只需将命令写入文件(fifo管道)。如果需要,可以将输出重定向到其他管道或一些简单文件中

要使fifo使用此简单命令:

mkfifo "FIFONAME"
runner守护进程将是一个简单的bash脚本,如下所示:

#!/bin/bash
while [ 1 ]
do
    cmd=$(cat FIFONAME | ( read cmd ; echo $cmd ) )
    # Validate the command
    ssh 192.168.0.1 "$cmd"
done
./wrapper reloadnginx
在此之后,您可以信任您的代码,如果您的php代码完全被黑客攻击,您的上游服务器仍然是安全的。在这种情况下,攻击者根本无法访问您的敏感数据。他可以向您的
运行程序
守护进程发送命令,但是如果您正确验证了命令,就不用担心了


:-)

老兄,那完全错了

您不想更改任何要创建新文件的配置文件,然后将其包含在默认配置文件中

例如,对于apache,您有*.conf文件和include指令。更改默认配置文件是完全疯狂的。我就是这样做的

您不需要ssh或类似的东西


相信我,如果你愿意,它会更好更安全。

方法1

我可能会用这个。写一点,确保它执行的所有命令都是预定义的,并且不能由php脚本控制。 因此,创建包装器并从ARGV获取命令。所以一个电话可能是这样的:

#!/bin/bash
while [ 1 ]
do
    cmd=$(cat FIFONAME | ( read cmd ; echo $cmd ) )
    # Validate the command
    ssh 192.168.0.1 "$cmd"
done
./wrapper reloadnginx
包装器然后执行
/etc/init.d/nginx reload

确保将
chown
包装到root和
chmod+s
。然后,它将生成根目录下的命令,但由于您预定义了所有命令,因此php脚本无法作为根目录执行任何其他操作

方法2

使用sudo并为某些命令设置它。通过这种方式,您可以实现相同的效果,并且只有某些应用程序可以生成为root。但是,您无法控制参数,因此请确保这些二进制文件中没有权限提升


你真的不想给PHP脚本完全的根访问权限。

你可以使用
setcap
来允许Nginx绑定到端口80/443,而不必以根用户身份运行。Nginx只需作为root运行即可绑定端口80/443(任何小于1024的端口)<代码>设置上限
详见

不过也有一些漏洞。您必须
chown
将日志文件发送给正确的用户(
chown-R nginx:nginx/var/log/nginx
),并将pid文件配置为
/var/run/
pid/path/to/nginx.pid
)之外的其他位置

lawl0r为setuid/sudo提供了一个很好的答案

作为最后一次恢复,如果配置发生更改,可以使用cron作业定期重新加载配置


无论哪种方式,当SSH在同一个系统上时,您都不需要它。

您到底在问什么?你想拥有最安全、最通用的选择吗?php脚本是否在同一台主机上运行,需要在该主机上编写更改或远程执行?我正在寻找最安全的选项。当前正在同一主机上运行。@nkamm在某些情况下,脚本的根权限是可行的,并且是合适的。将军