リモート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が文字列であり、リソースが指定されていることを期待しています」というエラーが発生しました。どうすればこれを解決できますか?
これを試して:
ステップ1。
MySQLデータベースサーバーへのSSHトンネルを設定します(セキュリティのために、Jumpbox経由が望ましい)。
ssh -fNg -L 3307:10.3.1.55:3306 username@ssh_jumpbox.com
ここで重要なのは-Lで、ローカルポートフォワーディングを実行していることを示しています。
ローカルポート転送構文
構文は少しトリッキーですが、次のように見ることができます:
<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パスフレーズ
クライアントとサーバー間のデータ交換は、暗号化されたSSH接続を介して送信され、安全です。
NB:データベースサーバーに直接トンネリングすることはお勧めしません。インターネットから直接アクセスできるデータベースサーバーを用意することは、大きなセキュリティ上の責任です。トンネルターゲットアドレスをジャンプボックス/要塞ホストのインターネットアドレス(手順1の例を参照)に、データベースターゲットをリモートネットワーク上のデータベースサーバーの内部IPアドレスにします。 SSHが残りを行います。
ステップ3。
PHPアプリケーションを次のように接続します:
<?php
$smysql = mysql_connect( "127.0.0.1:3307", "dbuser", "passphrase" );
mysql_select_db( "db", $smysql );
?>
http://chxo.com/be2/20040511_5667.html にあるChris Snyderのすばらしい記事の功績
要件に応じて、別のアプローチとして、SSHトンネリングがサポートされているGUI MySQLクライアント( http://www.sequelpro.com/ など)を使用するか、PuTTYを使用してポート転送を設定します。
UPDATE 1今日、私は secure pipes と呼ばれる実行可能な代替macOS GUI sshトンネリングツールをレビューしました。
私は同じことを探していましたが、外部コマンドを必要とせず、外部プロセスを管理したくありません。したがって、ある時点で、純粋なPHP任意のPHPストリームで動作できるMySQLクライアントを作成することはどれほど難しいのでしょうか?約半分かかりました。 MySQLプロトコルのドキュメントに基づく1日。
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を実装していませんが、すべてのプレーンテキストクエリで動作するはずです。これを使用する場合は注意してください。コードのテストはまだ十分ではなく、文字列エスケープコードは確認されていません。
残念ながら、phpが提供するssh2トンネルは、トンネルするローカルポートを指定できないため、リモートmysql接続を処理できないようです(ポート22またはリモートサーバーが実行されているsshポートでのみ機能します)。これに対する私の解決策は、exec()
演算子を使用してトンネルを開き、そこから通常どおりに接続することです。
exec('ssh -f -L 3307:127.0.0.1:3306 [email protected] sleep 10 > /dev/null');
$mysqli = new mysqli('127.0.0.1', 'user', 'password', 'database', '3307');
the docs によると、最後のパラメータは '/var/run/mysql/mysql.sock'のようなソケット名またはパイプ名であると想定されています。 UNIXソケットを使用して接続していないので、それは当てはまりません...そのままにしておいてください。
ルート認証情報と公開秘密鍵のペアの両方でsshを実行して試しましたが、phpコードではなくコマンドラインで接続できます。私もトンネルを作成して(ssh2関数を使用して)、phpコード(システム、実行など)からシェルコマンドを実行してみましたが、何も機能しませんでした。最後に私はシェルコマンドを実行するためにssh2関数を試しました、そしてそれは最終的にはうまくいきました:)それがあなたを助けるなら、これがコードです:----
$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関数を具体的に使用する場合は、これを試してみました。
Mysqlサーバーのユーザーが「localhost」からのみ許可するように設定されており、127.0.0.1ではなく、localhostのIPアドレスを許可するように設定されているためです。
私は次の手順を実行してこれを機能させました:
通常はサーバーにSSH接続し、mysql rootユーザーでログインして、次のコマンドを発行します。
GRANT ALL ON yourdbname.* TO [email protected] IDENTIFIED BY 'yourdbpassword';
もちろん、キーは上記の127.0.0.1を指定することです。
次のようにして、リモートMySQLサーバーへのローカルSSHトンネルを開始できます。
ssh -vNg -L 33306:127.0.0.1:3306 [email protected]
-v
は、sshを詳細モードで動作させます。これは、何が起こっているかを確認するのに役立ちます。たとえば、接続を試みると、ターミナルコンソールに次のようなデバッグ出力が表示されます。
debug1: client_input_global_request: rtype [email protected] 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
これは、リモートホストのローカルIPアドレス33306
に接続するローカルポート127.0.0.1
およびリモートホストのmysqlポート(通常は3306
)を指定するメインパラメーターです。
この後に必要なメカニズムやその他のパラメーターを使用して、SSH経由でリモートホストに接続できます。私の場合、~/.ssh/config
で構成されたキーファイルを使用しているので、user@Host
を指定するだけで取得できます。
このようなコマンドを発行すると、SSHがフォアグラウンドで実行されるため、Ctrl + C
で簡単に閉じることができます。このトンネルをバックグラウンドプロセスで実行する場合は、-f
を追加してこれを実行できます。
ローカルホストで上から実行されているSSHトンネルは、mysqlが127.0.0.1
で実行されているかのように動作します。ポート33306
(トリプル3に注意)を使用して、ローカルのSQLサーバーを通常のポートで実行できるようにします。これで、通常どおりに接続できます。端末のmysql
コマンドは次のようになります。
mysql -h 127.0.0.1 -P 33306 -u yourmysqluser -p
ここで、-P
(大文字のP)は、SSHトンネルのローカルエンドが接続を受け入れるポートを指定します。 mysql cliはLinuxソケットを使用して接続しようとするため、localhost
ではなく127.0.0.1
IPアドレスを使用することが重要です。
PHP接続文字列の場合、データソース名文字列(Yii2構成の場合)は次のようになります。
'dsn' => 'mysql:Host=127.0.0.1;dbname=yourdbname;port=33306',
パスワード、およびユーザー名は通常どおり指定されます。
接続先のユーザー名とパスワードに、適切なホスト名権限があることを確認してください。ワイルドカードに '%'を使用できると思います。また、ローカルネットワーク上にないリモートマシン(sshを実行しようとしている場合に想定)に接続している場合は、外部トラフィック用のサーバーがあるルーターのポートを転送する必要があります。接続できます。