web-dev-qa-db-ja.com

PHP)でSSH経由でMySQLサーバーに接続します

Sshを介してmysqlサーバーへのsshトンネルを確立したいと思います。

理想的には、直接接続していたのと同じようにmysqlidbポインターを返します。

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で共有CentOSLinuxホストを実行しています。

トンネルを永続化することについて何か考えはありますか?別のスクリプトでそれを確立し、PHPでそれを利用することは可能ですか?

ありがとう。

19
Eric Goodwin

エリック、

これは運が悪いと思います。 PHPコードでssh拡張機能を使用するか、サーバーにアクセスできる場合は、コマンドラインでsshトンネルを作成してみてください。

ただし、これを行うにはおそらく特別な権限が必要です。また、このホスティングアカウントへのsshアクセスがないようです。

-ジョアン

1
jpm

autossh ツールを使用して、mysqlデータベースへの永続的なsshトンネルを作成します。次に、PHPコードで行う必要があるのは、ローカルホストを指すことだけです。

これを(自動再起動なしで)テストするには、次のようにします。

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

パスワードを使用する必要がないようにsshキーを設定し、mysqlシステムの.ssh/authorized_keysファイルを微調整してポート転送にのみ使用できるようにします。

Sshのトリックの詳細については、 Brian Hatch's SSHとポート転送に関する優れたシリーズを参照してください。

14
Brian C. Lane

SQLアクションの実行中は、トンネルを開いたままにしておく必要があります。 RJMetrics からの次の例は説明します:

一般的なSSHコマンドの構文は次のとおりです。

_ssh -f -L bind-ip-address:bind-port:remote-ip-address:remote-port \
username@remote-server [command] >> /path/to/logfile
_

PHPコード:2行でリモートデータベース接続を安全に確立する方法は次のとおりです。

_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()関数を使用して転送ポートを使用してデータベース接続を開きます。 mysql_connect()ではポートを指定できず、_mysql_*_関数は非推奨であるため、ここでは「mysqli」ライブラリを使用する必要があることに注意してください。

_sleep 60_:トンネル接続に関しては、基本的に2つのオプションがあります。接続を常に開いたままにするか、必要に応じて接続を開いて閉じます。後者をお勧めします。そのため、トンネルを確立するときに_-N_オプションを指定しません。これにより、プロセスが手動で強制終了されるまでトンネルが開いたままになります(自動化には適していません)。 _-N_が指定されていないため、SSHセッションが何にも使用されなくなるとすぐに、トンネルは自動的に閉じます。これは理想的な動作ですが、トンネルを作成してからMySQL接続を起動してトンネル経由で実行するまでの数秒を除きます。この期間中に購入するために、トンネルの作成時に無害な_sleep 60_コマンドを発行します。これにより、トンネルが閉じる前に、トンネルを通過するために基本的に60秒かかります。その時間枠でMySQL接続が確立されている限り、すべて設定されています。

7
Sosy

ルート資格情報と公開秘密鍵のペアの両方でSSHを実行してみました。コマンドラインからは接続できますが、PHPコードからは接続できません。

また、(SSH2関数を使用して)トンネルを作成し、PHPコード(systemexecなど);なしからシェルコマンドを実行してみました。働いた。

最後に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関数を使用したい場合は、これを試してください。

6
spooja

それ可能ですが、なぜですか?必要以上に複雑で、エラーが発生しやすくなります。

データベースをローカルで実行できませんか?そうでない場合は、SQLite、XMLファイル、または個別のサーバーデーモンを必要としないその他のものを使用できませんか?

あなた本当にはPHPスクリプト内のトンネルを初期化したくない。SSHトンネルの初期化には長い時間がかかる(簡単に1〜2秒になる可能性があります)。つまり、データベースに接続するすべてのページの読み込み中に2秒の遅延が発生します。

これを持っている場合(これは強くお勧めしません)、最良の方法は、バックグラウンドで接続を維持するスクリプトを用意することです。

SSHキーペア を設定します。次に、 autossh 、または必要なSSHコマンドを実行する単純なスクリプトを使用して、プロセスが終了するまで待ってから、プロセスを再開します。よりインテリジェントで、10〜20秒ごとにコマンドを実行して、失敗した場合は再接続することもできます。

SSHキーペアを使用すると、スクリプトにリモートユーザーのパスワードをハードコーディングする必要はありません。リモートユーザーが実行できることを制限することをお勧めします(専用のトンネルユーザーを使用し、制限されたシェルを指定します。 this の質問を参照してください)

要するに、最初にSQLiteを試してから、XMLファイルを使用してデータを保存することがどれほど実現可能かを確認してから、ローカルMySQLサーバーの取得についてWebホストにバグを報告してみることを強くお勧めします次にSSHトンネリングオプションを調べます。

3
dbr

私はあなたの最善の策は別のホスティングプロバイダーを見つけることだと思います。 Webホストを完全に制御できるVPSソリューション(仮想プライベートサーバー)をお勧めします。ただし、デフォルトの構成が気に入らない場合は、自分でアップグレードできます。

1
Nathan Strong