27

我在远程 Linux 机器上有我的数据库,我想使用 SSH 和 PHP 函数进行连接(我目前正在使用 ssh2 库)。我尝试使用 mysql_connect,但是当我尝试使用此功能时,它使我无法访问(尽管我已授予权限):

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

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

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

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

我收到错误“mysqli_connect() 期望参数 6 是字符串,给定资源”。我该如何解决这个问题?

4

7 回答 7

49

SSH隧道解决方案

设置到 MySQL 数据库服务器的 SSH 隧道(通过 Jumpbox 代理以确保安全)。


(A) 图形用户界面工具

根据您的要求,您可以使用内置 SSH 隧道支持的 GUI MySQL 客户端,例如Visual Studio Code 转发端口/创建 SSH 隧道TablePlus或使用PuTTY设置本地端口转发。

在 macOS 上,我喜欢Secure PipesTablePlus


(B) 命令行

步骤1。

ssh -fNg -L 3307:10.3.1.55:3306 username@ssh-jumpbox.com 

这里的关键是“-L”开关,它告诉 ssh 我们正在请求本地端口转发。

我选择使用上面的3307端口。我的本地计算机上指向此端口的所有流量现在都将通过我的ssh 客户端“端口转发”到在 address 的主机上运行的ssh 服务器ssh-jumpbox.com

Jumpbox ssh 代理服务器将代表您解密流量并与您的 MySQL 数据库服务器建立网络连接10.3.1.55:3306,在这种情况下。MySQL 数据库服务器会看到来自 Jumpbox 内部网络地址的连接。


本地端口转发语法
语法有点棘手,但可以看作:

<local_workstation_port>:<database_server_addr_remote_end_of_tunnel>:<database_server_port_remote_end> username@ssh_proxy_host.com

如果您对其他开关感兴趣,它们是:

-f(进入后台)
-N(不执行远程命令)
-g(允许远程主机连接到本地转发端口)

私钥认证,在上面添加(-i)开关:

-i /path/to/private-key

第2步。

告诉你的本地 MySQL 客户端通过你的机器上的本地端口 3307 (-h 127.0.0.1) 通过你的 SSH 隧道连接,它现在转发通过你在步骤 1 中建立的 SSH 隧道发送到它的所有流量。

mysql -h 127.0.0.1 -P 3307 -u dbuser -p passphrase

客户端和服务器之间的数据交换现在通过加密的 SSH 连接发送并且是安全的。


安全注意事项
不要直接通过隧道连接到您的数据库服务器。拥有可从 Internet 直接访问的数据库服务器是一项巨大的安全责任。将隧道目标地址设置为 Jumpbox/Bastion 主机的 Internet 地址(请参见步骤 1 中的示例),并将您的数据库作为远程网络上数据库服务器的内部IP 地址。SSH 将完成其余的工作。


步骤 3。

现在连接您的 PHP 应用程序:

<?php
      $smysql = mysql_connect( "127.0.0.1:3307", "dbuser", "passphrase" );
      mysql_select_db( "db", $smysql ); 
?>

感谢Chris Snyder 的精彩文章,详细介绍了用于 MySQL 连接的 ssh 命令行隧道。

于 2013-04-22T02:09:52.663 回答
3

不幸的是,php 提供的 ssh2 隧道似乎无法处理远程 mysql 连接,因为您无法指定要隧道的本地端口(它仅适用于端口 22 或远程服务器运行的任何 ssh 端口)。我对此的解决方案是通过exec()运营商打开隧道并从那里照常连接:

exec('ssh -f -L 3307:127.0.0.1:3306 user@example.com sleep 10 > /dev/null');
$mysqli = new mysqli('127.0.0.1', 'user', 'password', 'database', '3307');
于 2017-09-12T19:28:25.987 回答
2

我一直在寻找同样的东西,但我更喜欢不需要外部命令和管理外部进程。所以在某些时候我想,编写一个可以在任何 PHP 流上运行的纯 PHP MySQL 客户端有多难?根据 MySQL 协议文档,我花了大约半天的时间。

https://gist.github.com/UCIS/4e509915ed221660e58f5169267da004

您可以将其与 SSH2 库或任何其他流一起使用:

    $ssh = ssh2_connect('ssh.host.com');
    ssh2_auth_password($ssh, 'username', 'password');
    $stream = ssh2_tunnel($ssh, 'localhost', 3306);
    $link = new MysqlStreamDriver($stream, 'SQLusername', 'SQLpassword', 'database');
    $link->query('SELECT * FROM ...')->fetch_assoc();

它没有实现完整的 mysqli API,但它应该适用于所有纯文本查询。如果你决定使用这个,请小心,我还没有彻底测试过代码,字符串转义代码也没有经过审查。

于 2019-03-17T17:14:32.603 回答
1

根据文档,最后一个参数应该是套接字或管道名称,例如“/var/run/mysql/mysql.sock”。由于您没有使用 UNIX 套接字进行连接,因此这不适用于您……所以请尝试将其排除在外。

于 2009-01-21T07:26:17.393 回答
1

我相信我(我想大多数人)在让它工作时遇到问题的原因是因为 mysql 服务器中的用户被设置为只允许来自“localhost”而不是 127.0.0.1,即 localhost 的 IP 地址。

我通过执行以下步骤使其工作:

第 1 步:允许目标用户使用 127.0.0.1 主机

SSH 正常进入您的服务器,并使用 mysql root 用户登录,然后发出命令:

GRANT ALL ON yourdbname.* TO yourdbuser@127.0.0.1 IDENTIFIED BY 'yourdbpassword';

当然,关键是在上面指定 127.0.0.1。

第 2 步:启动到 MySQL 的本地 SSH 隧道

您现在可以启动到远程 MySQL 服务器的本地 SSH 隧道,如下所示:

ssh -vNg -L 33306:127.0.0.1:3306 sshuser@remotehost.com

-v使 ssh 以详细模式运行,这有助于查看正在发生的事情。例如,当您尝试连接时,您会在终端控制台中看到如下调试输出:

debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Connection to port 33306 forwarding to 127.0.0.1 port 3306 requested.

关闭连接时输出如下:

debug2: channel 2: is dead
debug2: channel 2: garbage collecting
debug1: channel 2: free: direct-tcpip: listening port 33306 for 127.0.0.1 port 3306, connect from 127.0.0.1 port 52112 to 127.0.0.1 port 33306, nchannels 3

-N使 ssh 不发出任何命令,而是在建立连接后等待。

-g允许远程主机连接到本地转发端口。不完全确定这是否有必要,但它可能对通过同一 SSH 隧道多路复用多个连接很有用。

-L这是主要参数,指定33306连接远程主机的本地IP地址127.0.0.1和远程主机的mysql端口的本地端口,通常3306.

在此之后,您可以使用所需的任何机制/其他参数通过 SSH 连接到远程主机。在我的情况下,我使用我配置的密钥文件,~/.ssh/config所以我只需要指定user@host进入。

发出这样的命令会在前台运行 SSH,因此我可以使用Ctrl + C. 如果您想在后台进程中运行此隧道,您可以添加-f来执行此操作。

第 3 步:从 PHP/其他 mysql 兼容方法连接

在您的 localhost 上从上面运行的 SSH 隧道的行为将与您的 mysql 在127.0.0.1. 我使用端口33306(注意三个 3),它可以让我在其正常端口上运行我的本地 sql 服务器。您现在可以像往常一样连接。终端上的mysql命令如下所示:

mysql -h 127.0.0.1 -P 33306 -u yourmysqluser -p

其中-P(大写 P)指定 SSH 隧道的本地端接受连接的端口。使用127.0.0.1IP 地址而不是localhost因为 mysql cli 可能会尝试使用 linux 套接字进行连接,这一点很重要。

对于 PHP 连接字符串,我的数据源名称字符串(对于我的 Yii2 配置)如下所示:

'dsn' => 'mysql:host=127.0.0.1;dbname=yourdbname;port=33306',

密码和用户名按正常方式指定。

于 2017-11-21T07:26:11.907 回答
0

即使我尝试通过根凭据和公钥对执行 ssh 来尝试它,但它允许我通过命令行而不是通过 php 代码连接。我也尝试通过创建隧道(通过使用 ssh2 函数),从 php 代码(系统、执行等)运行 shell 命令,但没有任何效果。最后我尝试了 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 函数,它对我有用。

于 2009-01-23T11:23:33.637 回答
0

确保您连接的用户名和密码具有正确的主机名权限。我相信您可以使用 '%' 作为通配符。此外,如果您要连接到不在本地网络上的远程计算机(如果您尝试 ssh 进入它,我会假设您是),您将不得不转发路由器上的端口,服务器所在的服务器用于外部流量能够连接到它。

http://www.lanexa.net/2011/08/create-a-mysql-database-username-password-and-permissions-from-the-command-line/

于 2017-03-25T21:44:54.443 回答