質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

XAMPP

XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

Q&A

解決済

1回答

353閲覧

XAMPPを使いSSH通信で外部のMySQLに接続したい

RAIRU

総合スコア3

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

XAMPP

XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

0グッド

0クリップ

投稿2024/03/07 01:25

編集2024/03/08 09:49

実現したいこと

XAMPPを使ってSSH通信で外部のMySQLからDBに接続し、データを取得するクエリを実行する。
クエリ実行やセキュリティ対策は一先ずおいて起き、まずは接続を確立させたい。

発生している問題・分からないこと

「Fatal error: Uncaught mysqli_sql_exception: Access denied for user 'okane_db'@'localhost' (using password: YES) in C:\xampp\htdocs\today.php:34 Stack trace: #0 C:\xampp\htdocs\today.php(34): mysqli_connect('localhost', 'okane_db', 'pepepe', 'okane_db', 3306) #1 {main} thrown in C:\xampp\htdocs\today.php on line 34」
というエラーが発生し、接続が拒否される。

該当のソースコード

php

1<?php 2 3// SSH接続情報 4$ssh_host = "okane.sakura.ne.jp"; // SSHサーバーのホスト名 5$ssh_port = 22; // SSHポート番号 6$ssh_user = "okane"; // SSHユーザー名 7$ssh_password = "******"; // SSHパスワード 8 9// MySQL接続情報 10$mysql_host = 'localhost'; // ローカルホスト 11$mysql_port = 3306; // ローカルMySQLポート番号 12$mysql_user = "okane_db"; // MySQLユーザー名 13$mysql_password = "pepepe"; // MySQLパスワード 14 15// SSH接続を確立 16$connection = ssh2_connect($ssh_host, $ssh_port); 17if (!$connection) { 18 die('SSH connection failed'); 19} 20 21// SSHユーザー名とパスワードで認証 22if (!ssh2_auth_password($connection, $ssh_user, $ssh_password)) { 23 die('SSH authentication failed'); 24} 25 26// SSHトンネルを作成(ローカルポートフォワーディング) 27$forwarded_port = ssh2_tunnel($connection, $mysql_host, $mysql_port); 28if (!$forwarded_port) { 29 die('Failed to create SSH tunnel'); 30} 31 32// MySQLに接続 手続き型 33 34$mysql_connection = mysqli_connect($mysql_host, $mysql_user, $mysql_password, "okane_db", $mysql_port); 35 36// 接続エラーをチェック 37if (mysqli_connect_errno()) { 38 die('MySQL connection failed: ' . mysqli_connect_error()); 39} 40 41 42// 接続成功時の処理 43echo 'Connected to MySQL via SSH tunnel'; 44 45// ここでMySQLクエリを実行するなどの処理を行う 46 47// MySQL接続を閉じる 48if($mysql != null){ 49 mysqli_close($mysql); 50} 51 52// SSH接続を閉じる 53ssh2_disconnect($connection); 54 55?> 56

php.ini

1[Syslog] 2define_syslog_variables=Off 3[Session] 4define_syslog_variables=Off 5[Date] 6date.timezone=Europe/Berlin 7[MySQL] 8mysql.allow_local_infile=On 9mysql.allow_persistent=On 10mysql.cache_size=2000 11mysql.max_persistent=-1 12mysql.max_link=-1 13mysql.default_port=3306 14mysql.default_socket="MySQL" 15mysql.connect_timeout=3 16mysql.trace_mode=Off 17[Sybase-CT] 18sybct.allow_persistent=On 19sybct.max_persistent=-1 20sybct.max_links=-1 21sybct.min_server_severity=10 22sybct.min_client_severity=10 23[MSSQL] 24mssql.allow_persistent=On 25mssql.max_persistent=-1 26mssql.max_links=-1 27mssql.min_error_severity=10 28mssql.min_message_severity=10 29mssql.compatability_mode=Off 30mssql.secure_connection=Off 31 32extension=php_ssh2.dll

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

1:ユーザ名やパスワードといった接続情報に間違いがないが確認した
→正しい情報だったが接続が拒否された

2:オブジェクト指向型の「mysqli()」やPOD型の「POD()」での接続を試した
→同様のエラーが発生した

3:phpMyAdminを使っての接続を試した
→同様のエラーが発生した

4:ローカル環境でMySQLとDBを作成し、上記と同様の方法で接続をした
→接続の確認が出来た

5:接続したいDBの権限を確認した
→ GRANT USAGE ON . TO 'okane_db'@'localhost'
GRANT ALL PRIVILEGES ON okane_db.* TO 'okane_db'@'localhost'

6:接続したいDBのuserデータ等をコマンドで確認した
→root情報の接続が権限に付与されておらず確認できなかった

7:ポート番号の重複がないよう調整し、システムからMySQLを起動してphpから接続を試した
→接続が拒否された

ー追記 2024/03/08 18:47ー
8:$forwarded_portをポートとして接続する
→String、intどちらでもないため、引数として機能しなかった

9:バックグラウンドでsshトンネルを事前に掘る
→調べ方が悪いのか、全然わからない

現状:接続拒否が解決できていない

補足

PHP Version 8.1.25

SSH2 support
extension version 1.3.1
libssh2 version 1.10.0

環境 Windows10 Pro

コード一部情報は加工してあります。

最終的にはこのphpをAndroidStudio Javaから実行したく、その前段階の環境構築・検証として作成しました。
PHP関連の知識はほとんどないので手探り状態となっております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AbeTakashi

2024/03/07 07:17

ざっくりみただけですが、mysqli_connectで$mysql_hostを使用してるのでトンネルを利用せずに単純にローカルホストに接続しにいってますね。この部分はトンネル($forwarded_port)を利用するように直す必要があるでしょう。 あと、 https://www.php.net/manual/ja/mysqli.construct.php みると If you want to connect via an alternate port (other than 3306), as you might when using an ssh tunnel to another host, using "localhost" as the hostname will not work. Using 127.0.0.1 will work. Apparently, if you specify the host as "localhost", the constructor ignores the port specified as an argument to the constructor. とあるので、localhostではなく127.0.0.1を使った方がいいかもしれません。
RAIRU

2024/03/07 07:46

下記の通り修正してみました。 $mysql_host = '127.0.0.1' $mysql_connection = mysqli_connect($mysql_host, $mysql_user, $mysql_password, 'okane_db', $forwarded_port); 以下のエラーが発生しました。 Fatal error: Uncaught TypeError: mysqli_connect(): Argument #5 ($port) must be of type ?int, resource given in C:\xampp\htdocs\today.php:34 Stack trace: #0 C:\xampp\htdocs\today.php(34): mysqli_connect('127.0.0.1', 'okane_db', 'pepepe', 'okane_db', Resource id #3) #1 {main} thrown in C:\xampp\htdocs\today.php on line 34 エラーの内容的に「$forwarded_port」が?int型でなければならないが、 $forwarded_port = ssh2_tunnel($connection, $mysql_host, $mysql_port); での戻り値がその型に合わないから、かと思われます。 この場合、型を適合する形に変換すればいいのでしょうか。
AbeTakashi

2024/03/07 08:08

$forwarded_portってsshトンネルオブジェクトのインスタンスとかですよね? Portに指定するのはおかしいと思いますが。 $mysql_connection = mysqli_connect($forwarded_port, $mysql_user, $mysql_password, 'okane_db'); みたいに使うんじゃないですかね? 自信ありませんけど・・・
RAIRU

2024/03/07 23:50

返信が遅くなり、申し訳ございません。 頂いたコードを検証しました結果、以下のエラーが発生しました。 Fatal error: Uncaught TypeError: mysqli_connect(): Argument #1 ($hostname) must be of type ?string, resource given in C:\xampp\htdocs\today.php:34 Stack trace: #0 C:\xampp\htdocs\today.php(34): mysqli_connect(Resource id #3, 'okane_db', 'pepepe', 'okane_db') #1 {main} thrown in C:\xampp\htdocs\today.php on line 34 mysqli_connect()の返り値はintでもなくstringでもない、ということがわかりました。 ならばとその返り値$mysql_connectionを試しにstringに変換してみました。 $mysql_connection = mysqli_connect("$forwarded_port", $mysql_user, $mysql_password, 'okane_db'); 結果、以下のエラーが発生しました。 Warning: mysqli_connect(): php_network_getaddresses: getaddrinfo for Resource id #3 failed: ���̂悤�ȃz�X�g�͕s���ł��B in C:\xampp\htdocs\today.php on line 34 Fatal error: Uncaught mysqli_sql_exception: php_network_getaddresses: getaddrinfo for Resource id #3 failed: ���̂悤�ȃz�X�g�͕s���ł��B in C:\xampp\htdocs\today.php:34 Stack trace: #0 C:\xampp\htdocs\today.php(34): mysqli_connect('Resource id #3', 'okane_db', 'pepepe', 'okane_db') #1 {main} thrown in C:\xampp\htdocs\today.php on line 34 ローカルポートフォワーディングの概要は理解出来たのですが、このmysqli_connect()の仕様がいまだにちゃんと理解できていない点が悔しいです。
AbeTakashi

2024/03/08 02:04

そうするとmysqli_connectがssh2_tunnelに対応してない可能性が高そうですね。ググるとわりと出てきますが、shell_execをつかってトンネルを掘って、そこから接続('127.0.0.1')してるような方法をとってる人が多いです。 参考 https://stackoverflow.com/questions/18069658/connect-to-a-mysql-database-via-ssh-through-php Windowsだとちょっとやり方変える必要ありそうですが、こちらの方法を模索された方が良さそうな気がします。
tezcello

2024/03/08 03:54

XAMPPという事は開発環境ですよね? だったら、都度コマンドラインでトンネルを開通させてからPHPを実行するだけでは? それとも本番環境でもトンネル経由でアクセスしたいのでしょうか?
RAIRU

2024/03/08 04:29

ここでの質問では必要ないと思い入れててはなかったのですが、最終目標はこのphpをAndroidアプリで実行させたいです。 そのための環境、そのためのXAMPP、ということで使っております。 Android関連は一先ず置いておき、まずはphpで正常に接続したいです。 XAMPPが開発環境で都度コマンドを打てばいいということは、php実行前にコマンドプロンプトかpowershellかで通信「ssh ユーザー名@リモートホスト」を実行させておけばいい、ということですか?
AbeTakashi

2024/03/08 05:58

OSレベルであらかじめコマンドでトンネルを掘っておいて、そこにPHPから接続しに行くって形になるので、PHP側ではトンネルを意識せずに普通に mysqli_connect('127.0.0.1',....... ってやればいいということになると思います。
RAIRU

2024/03/08 07:36

OSレベルで、ということはシェルスクリプト(.sh)を作成し、そこにSSH通信を行うスクリプトを書く。書いたシェルスクリプトをPHPのshell_exec()で呼び出して実行する、という認識でよろしいでしょうか。 記述しているphpファイルと同じフォルダに作成し、相対パスを渡す手法を試しました。 NULLが返されたのでやり方が違うのかな、と色々試しております。
AbeTakashi

2024/03/08 08:38

PHPを起点としたいと言うことだと思いますが、それはシェルスクリプト経由でも直接execしてもどちらでも良いと思います。権限まわりとかパスの問題とかで色々とややこしいのかもしれませんが、私は普段使いはWindowsではないので、その辺の知識は全然ありません。すいません。
tezcello

2024/03/08 09:50

PHPスクリプトを実行する前に、ターミナルでトンネルを確立しておけば良いのだろうと思います。 実運用時は、トンネル経由じゃなくそのサーバからは件のデータベースに接続できるようしておけば良いと思いますけど?
RAIRU

2024/03/08 10:17 編集

ターミナルでの確立、ということは 例えば「ssh -f -N -L 3307:localhost:3306 'ユーザ名'@'ホスト名' &」をWindowsのコマンドプロンプト等で事前に入力しておいてからphp通信を行う、という解釈でしょうか。 無知な事だらけで申し訳ございません。
tezcello

2024/03/08 11:01

そのコマンドをバックグラウンドで実行しなくても良いんじゃないかと...
RAIRU

2024/03/11 03:00

時間が経過して申し訳ございません。 色々と調べてみました結果、Windowsターミナルにたどり着きました。 そこで事前にSSH通信を出来るよう、コマンドを入力しました。 その後、接続できている状態でXAMPPを起動し、localhost/〇〇.php(今回動かしたいPHP)をchromeで起動しましたところ、以下のエラーが発生しました。 Fatal error: Uncaught mysqli_sql_exception: 対象のコンピューターによって拒否されたため、接続できませんでした。 in C:\xampp\htdocs\today.php:46 Stack trace: #0 C:\xampp\htdocs\today.php(46): mysqli_connect('localhost', 'okane_db', 'pepepe', 'okane_db') #1 {main} thrown in C:\xampp\htdocs\today.php on line 46 (一部情報加工) コマンド上では問題なく接続できるのに、PHPを介すと途端にできなくなってしまいます。 ここがどうしてもわかりません。
tezcello

2024/03/11 10:34

> ssh -f -N -L 3307:localhost:3306 'ユーザ名'@'ホスト名' > その後、接続できている状態でXAMPPを起動し(略)以下のエラーが発生しました。 > Fatal error: Uncaught mysqli_sql_exception: 対象のコンピューターによって拒否されたため、接続できませんでした。 in C:\xampp\htdocs\today.php:46 > mysqli_connect('localhost', 'okane_db', 'pepepe', 'okane_db') そのトンネル設定だと、ローカルの3307ポートにアクセスする必要があるのでは? php.iniで指定していれば別だけど、エラーメッセージの通りに呼び出しているなら、接続ポートが違うと思います。
RAIRU

2024/03/11 23:36

ローカルの3307ポートにアクセスしたところ問題が解決しました! こんな簡単な事に気付けるようになるまで、長かったです......。 ベストアンサーに選びたいので同じ内容を回答欄に投稿いただけますでしょうか?
guest

回答1

0

ベストアンサー

お試しで使うだけなら、事前にトンネルを掘っておいて、後は普通にアクセスするのが良いと思います。
実運用時にはローカルにDBがあるのかもしれないですし、アクセスの度に接続しにいくってのも…

一応やりたい事が出来た様なのは何よりです。

ssh -f -N -L 3307:localhost:3306 'ユーザ名'@'ホスト名'
ローカルの3307ポートにアクセスしたところ問題が解決
こんな簡単な事に気付けるようになるまで、長かった

ネットに限らず、拾ってきた情報を「何をやっているか」を調べもしないでそのまま使っているとハマります。

まぁ、この例の様に、リモートとは異なるポートでフォワードをするのは、ポートの繋ぎ替えが出来るのを明確にする為でしょうが、現実的にはあまり意味が無いかなぁと思っています。
__ローカルと競合する場合に別ポートでリモートへ渡すなら理解できるけど

投稿2024/03/12 01:55

tezcello

総合スコア167

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RAIRU

2024/03/12 01:59

この度はご親切にありがとうございました。 皆様にこの場をお借りしてお礼申し上げます >ネットに限らず、拾ってきた情報を「何をやっているか」を調べもしないでそのまま使っているとハマります。 焦っていたのもあってか、おろそかにしておりました。肝に銘じます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問