2008-11-21 280 views
18

我想通过SSH建立一个ssh隧道到我的mysql服务器。通过SSH在PHP连接到MySQL服务器

理想情况下,我会返回一个mysqli数据库指针,就像我直接连接。

我在没有SSH2库的共享主机上,但我可能能够使用PECL在本地安装它们。

如果有一种方法使用原生命令,那就太好了。

我在想这样的事情,但没有这些库,它将无法正常工作。

$connection = ssh2_connect('SERVER IP', 22); 

ssh2_auth_password($connection, 'username', 'password'); 

$tunnel = ssh2_tunnel($connection, 'DESTINATION IP', 3307); 

$db = new mysqli_connect('127.0.0.1', 'DB_USERNAME', 'DB_PASSWORD', 
         'dbname', 3307, $tunnel) 
    or die ('Fail: ' . mysql_error()); 

任何人有任何想法?我正在Liquidweb上运行共享的CentOS Linux主机。

任何关于使隧道持续的想法?是否可以使用另一个脚本来建立它,并在PHP中利用它?

谢谢。

+0

您意识到该共享主机上的其他人也将能够连接到您的数据库吗? – Zoredache 2008-11-21 18:01:23

+0

它仍然需要有效的用户名和密码才能连接,但这是一个明确的风险。如果隧道是在php中每次执行创建的,情况会是这样吗? – 2008-11-21 18:09:48

+0

我删除了我以前的答案,正如我在阅读文档时注意到的那样,它比我想要获得mysqli使用SSL更多。 – Powerlord 2008-11-21 18:20:38

回答

0

埃里克,

我认为你在这一个运气不好。你可以在你的PHP代码中使用ssh扩展,或者你可以访问服务器,你可以尝试在命令行上创建一个ssh隧道。

虽然你可能需要特殊的权限来做到这一点。它也看起来像你没有ssh访问这个托管帐户。

--Joao

1

我认为最好的办法是找到一个不同的托管服务提供商;我建议一个VPS解决方案(虚拟专用服务器),它可以让你完全控制你的网络主机。那么,如果你不喜欢默认配置,你可以自己升级它。

14

我会使用autossh工具来创建一个持久的ssh隧道到你的mysql数据库。然后,您只需将PHP代码指向localhost即可。

您可以在此(没有自动启动)做测试:

ssh -L 3306:localhost:3306 [email protected] 

设置一个SSH密钥,这样你就不需要使用密码,以及调整MySQL的系统上的.ssh/authorized_keys文件只允许它用于端口转发。

有关ssh技巧的更多信息,请参阅Brian Hatch's关于SSH和端口转发的优秀系列。

+0

这个答案让我走上了正确的轨道。我终于明白了这一点:http://stackoverflow.com/questions/464317/connect-to-a-mysql-server-over-ssh-in-php#comment65229024_16138417 – Ryan 2016-08-13 19:59:17

2

可能,但为什么?它比需要更复杂,并且容易出错。

你不能在本地运行数据库吗?如果没有,你不能使用SQLite,XML文件或其他不需要单独服务器守护进程的东西吗?

真的不想初始化PHP脚本中的隧道。初始化一个SSH隧道需要很长时间(可以轻松一秒钟或两秒钟),这意味着每个连接到数据库的页面在加载时都会有2秒的延迟。

如果做到这一点(我强烈反对),最好的方法是将有维持在后台连接的脚本..

设置一个SSH keypair。然后使用autossh或执行所需SSH命令的简单脚本,等到该进程死亡并重新启动。它可能更智能,每10-20秒尝试运行一次命令,如果失败则重新连接。

使用SSH密钥对,你就不必硬编码在脚本中的远程用户的密码。我建议限制远程用户可以做什么(通过使用专用的隧道用户,并给它一个受限制的shell,请参阅this问题)

总之,我强烈建议先尝试SQLite,然后看看它是如何可行的使用XML文件存储数据,然后尝试窃听您的Web主机获取本地MySQL服务器,然后然后查看SSH隧道选项。

6

我做SSH都是由根证书和公共密钥对尝试过。它允许我通过命令行而不是通过PHP代码。我也试过创建一个隧道(通过使用SSH2函数),并从PHP代码运行shell命令(systemexec等);没有工作。

最后我想SSH2函数执行shell命令,它终于摸索:)

这里是我的代码,如果它可以帮助你:

$connection = ssh2_connect($remotehost, '22'); 
if (ssh2_auth_password($connection, $user,$pass)) { 
    echo "Authentication Successful!\n"; 
} else { 
    die('Authentication Failed...'); 
} 


$stream=ssh2_exec($connection,'echo "select * from zingaya.users where id=\"1606\";" | mysql'); 
stream_set_blocking($stream, true); 
while($line = fgets($stream)) { 
    flush(); 
    echo $line."\n"; 
} 

试试这个,如果要专门使用PHP函数。

6

隧道必须在SQL操作(一个或多个)的过程中,可以保持开放。从RJMetrics以下举例说明:

这里是通用的SSH命令语法:

ssh -f -L bind-ip-address:bind-port:remote-ip-address:remote-port \ 
[email protected] [command] >> /path/to/logfile 

以下是如何安全地建立在短短2行的PHP代码远程数据库的连接:

shell_exec("ssh -f -L 127.0.0.1:3307:127.0.0.1:3306 [email protected] sleep 60 >> logfile"); 
$db = mysqli_connect("127.0.0.1", "sqluser", "sqlpassword", "rjmadmin", 3307); 

我们使用shell_exec()函数创建具有60秒打开窗口的隧道,然后使用mysqli_connect()函数使用转发的端口打开数据库连接。请注意,我们必须在这里使用“mysqli”库,因为mysql_connect()不允许我们指定端口,而mysql_*函数已弃用。

sleep 60:当涉及到的隧道连接,我们基本上有两种选择:离开连接打开所有的时间或将其打开,并根据需要将其关闭。我们更喜欢后者,因此我们在建立隧道时没有指定-N选项,这会使其保持打开状态,直到手动终止进程(对自动化不利)。由于没有指定-N,所以只要SSH会话没有被用于任何事情,我们的隧道就会自动关闭。这是理想的行为,除了创建隧道和我们通过隧道启动并运行MySQL连接之间的几秒之外。为了在此期间购买我们一段时间,我们在创建隧道时发出无害的sleep 60命令,这基本上会让我们花费60秒在隧道关闭之前让其他东西通过隧道。只要在这个时间框架内建立了MySQL连接,我们就已经完成了。