C#でXSERVERのMySQLを使ったプログラムを作る必要があったのですが、最初は簡単にできると思っていたのですが、かなり手こずったので完成した結果を記録に残します。
XSERVERのSSHキー
前提としてXSERVERのSSHキー(秘密の鍵)を取得していることです。
⇩秘密の鍵の取得方法
処理の順番
接続から解放までの順番。
- sshキーを取得
- ssh接続
- ポートフォワーディング開始
- MySQL接続
- 任意のSQL文を発行して必要なロジックを実行
- MySQL解放
- ポートフォワーディング終了
- ssh解放
凄く簡単ですがこのような流れになります。
必要な情報
C#でコードを書く上で必要になるXSERVERに関係する内容です。
sshキー
sshキーを取得してダウンロードされて、それを保存しているパス。
sshキー取得時に設定したパスフレーズ。
sshキー取得時に入力したパスフレーズは忘れないように何かに書き留める等して忘れないようにして下さい。
サーバーID
サーバーパネルにログインする時に使っているサーバーIDとパスワードです。
サバーIDはサーバーパネルで確認できます。
サーバーパネルのアカウントデータに表示されています。
サーバーパネルログインパスワード
サーバーパネルログインパスワードはどこにも表示されないので、契約時に決定した内容です。
契約時の内容はテキスト形式等で大事に保管することをお勧めします。
サーバーアドレス
サーバーアドレスはサーバーパネルのサーバー情報で確認できます。
ホスト名、もしくはIPアドレスを使用します。
SSH接続ポート
通例では接続ポートは22ですが、SSH接続では10022になります。
ローカルアドレス
127.0.0.1にしました。
他のアドレスでも可能だと思うのですが、試していません。
ローカルポート
13306にしました。
使われていないポートであれば任意のポートいいようです。
XSERVER MySQLアドレス
サーバーパネルのMySQL設定で確認することが出来ます。
MySQLホスト名、もしくはMySQLIPアドレスの内容を使用します。
XSERVER MySQLポート
標準的な3306ポートを使用します。
XSERVERのMySQLのデータベースに接続するユーザーID
サーバーパネルのMySQL設定、MySQL一覧で確認できます。
アクセス権所有ユーザーをクリックしてみて下さい。
xxxxxx(サーバーアドレス)が表示されるので、()の前のxxxxxxがアクセス権を所有したユーザーIDになります。
データベースに接続するパスワード
データベースに接続するユーザーIDのパスワードになります。
確認にすることはできませんが、データベースに接続可能なユーザーIDを設定したときに指定したパスワードになります。
XSERVERのMySQLのデータベース
サーバーパネルのMySQL設定で確認することができます。
データベース名はサーバーID_xxxxxxとなっているはずです。
データベースにアクセスするユーザーID
サーバーパネルのMySQL設定で確認できます。
接続対象となるデータベースのアクセス権所有ユーザです。
アクセス権所有ユーザーのパスワード
これはMySQL設定のMySQLユーザ追加時に設定したパスワードが必要です。
見ることが出来ないので、忘れてしまったら対象ユーザーIDに対してパスワードを変更することができます。
ライブラリ
SSHとMySQLを使うので関連するライブラリをインストールします。
SSH | SSH.NET | Visual StudioであればNuGetパッケージの管理 |
MySQL | MySql.Data | Visual Studioであれば参照追加 |
SSHとポートフォーワディングのコード
using System;
using Renci.SshNet; // ①
// *******************************************************************
// SSHでXSERVERのMySQLに接続する
// *******************************************************************
class Ssh
{
const string ServeAddress = "999.999.999.999"; // ②
const int SshPort = 10022; // ③
const string ServerUserId = "xxxxxxxxxxxx"; // ④
const string ServerPassword = "xxxxxxxx"; // ⑤
const string SshKey = @"C:\xxxxxx\xxxxxxxxxxxxxxxx.key"; // ⑥
const string SshKeyPassPhrase = "xxxxxxxx"; // ⑦
const string LocalAddress = "127.0.0.1"; // ⑧
const int LocalPort = 13306; // ⑨
const string MySqlAddress = "999.999.999.999"; // ⑩
const int MySqlPort = 3306; // ⑪
public const bool ConstOK = true;
public const bool ConstNG = false;
public SshClient SshClient;
public ForwardedPortLocal ForwardedPortLocal;
// *******************************************************************
// SSHでXSERVERのMySQLに接続する
// *******************************************************************
public bool SshConnect()
{
// SSH接続
try
{
var _PassAuth = new PasswordAuthenticationMethod(ServerUserId, ServerPassword); // パスワード認証
// 秘密鍵認証
var _PrivateKey = new PrivateKeyAuthenticationMethod(ServerUserId, new PrivateKeyFile[]
{
new PrivateKeyFile(SshKey, SshKeyPassPhrase)
});
// 接続情報の生成
ConnectionInfo ConnNfo = new ConnectionInfo(ServeAddress, SshPort, ServerUserId,new AuthenticationMethod[]
{
_PassAuth, // パスワード認証
_PrivateKey, // 秘密鍵認証
});
SshClient = new SshClient(ConnNfo); // sshクライアント生成
SshClient.Connect(); // ssh接続
if(!SshClient.IsConnected)
{
Console.WriteLine("SSH Connection Error No1");
return ConstNG;
}
}
catch(Exception ex)
{
Console.WriteLine("SSH Connection Error No2");
Console.WriteLine(ex.Message);
return ConstNG;
}
return ConstOK;
}
// *******************************************************************
// SSHクローズ
// *******************************************************************
public void SshDeconnect()
{
SshClient.Disconnect();
}
// *******************************************************************
// ポートフォワーディング開始
// *******************************************************************
public bool PortForwardStart()
{
try
{
ForwardedPortLocal = new ForwardedPortLocal(LocalAddress,LocalPort,MySqlAddress,MySqlPort);
SshClient.AddForwardedPort(ForwardedPortLocal);
ForwardedPortLocal.Start();
if (!ForwardedPortLocal.IsStarted)
{
Console.WriteLine("forwardedPortLocal ERROR No1");
return ConstNG;
}
// var BoundHostaddress = ForwardedPortLocal.BoundHost;
// var BoundHostPort = ForwardedPortLocal.BoundPort;
}
catch(Exception ex)
{
Console.WriteLine("forwardedPortLocal ERROR No2");
Console.WriteLine(ex.Message);
return ConstNG;
}
return ConstOK;
}
// *******************************************************************
// ポートフォワーディング終了
// *******************************************************************
public void PortForwardStop()
{
ForwardedPortLocal.Stop();
}
}
SSSとポートフォワーディングをまとめたクラスを作りました。
メソッドの機能
メソッド | 機能 |
SshConnect() | SSH接続開始 |
SshDeconnect() | SSH接続解除 |
PortForwardStart() | ポートフォワーディング開始 |
PortForwardStop() | ポートフォワーディング終了 |
①~⑪の説明
番号 | 説明 |
① | SSH.NETを使用 |
② | XSERVERのIPアドレス、もしくはサーバーのホスト名 ホスト名の例:sv9999.xserver.jp |
③ | XSERVERのSSH接続は10022 |
④ | サーバーのユーザーID |
⑤ | サーバーパネルにログインするパスワード |
⑥ | SSHキーファイルのフルパス |
⑦ | XSERVERでSSHキーを取得した時のパスフレーズ |
⑧ | ローカルプログラムからアクセスするローカルアドレス |
⑨ | ローカルポート |
⑩ | XSERVERのMySQLのIPアドレスもしくはMySQLのホスト名 MySQLホスト名の例:mysql9999.xserver.jp |
⑪ | XSERVERのMySQLポート |
XSERVERのMySQLに接続するコード
先程作ったclass Sshを使ってXSERVERのMySQLに接続するコードの抜粋です。
通常の接続と異なるところはMySQLサーバーに接続するのではなくポートフォワードに接続するようになります。
using System;
using MySql.Data.MySqlClient; // ①
class MySQL
{
public MySqlConnection Connection = new MySqlConnection();
public bool CONST_OK = true;
public bool CONST_NG = false;
public string CONST_Server = null; // ②
public uint CONST_Port = 0; // ③
public string CONST_UserId = "xxxxxxxxxxxxxxxx"; // ④
public string CONST_Password = "xxxxxxxx"; // ⑤
public string CONST_Database = "xxxxxxxxxxxxxxxxxxxxxxx"; // ⑥
Ssh Ssh = new Ssh(); // ⑦ ssh接続クラス
// ***********************************************************
// MySQL(sssproduct)接続
// ***********************************************************
public bool Connect()
{
// ssh接続
if ( Ssh.SshConnect() == Ssh.ConstNG )
{
Console.WriteLine("SSH接続エラー");
return CONST_NG;
}
// ポートフォワーディング開始
if ( Ssh.PortForwardStart() == Ssh.ConstNG )
{
Console.WriteLine("ポートフォワーディング開始");
return CONST_NG;
}
try
{
CONST_Server = Ssh.ForwardedPortLocal.BoundHost; // ⑧
CONST_Port = Ssh.ForwardedPortLocal.BoundPort; // ⑨
Connection.ConnectionString = string.Format("Server={0};Database={1};Uid={2};Pwd={3};Port={4};Pooling=False;",
CONST_Server, CONST_Database, CONST_UserId, CONST_Password,CONST_Port);
Connection.Open();
}
catch (MySqlException e)
{
Console.WriteLine(string.Format("DATABASE:{0} CONNECT ERROR",CONST_Database));
Console.WriteLine(e.Message);
return CONST_NG;
}
return CONST_OK;
}
// ***********************************************************
// MySQL(sssproduct)解放
// ***********************************************************
public void DeConnect()
{
Ssh.PortForwardStop();
Ssh.SshDeconnect();
Connection.Close();
}
}
メソッドの解説
メソッド | 説明 |
Connect() | XSERVERのMySQLデータベースに接続します。
データベースに接続する前にSSHとポートフォワーディングを開始します。 |
DeConnect() | XSERVERのMySQLデータベース接続を解放します。
データベースを解放する前にポートフォワーディングとSSHを終了します。 |
①~⑨の解説
番号 | 解説 |
① | MySql.Dataを使用 |
② | ポートフォワードで取得した値を代入 |
③ | ポートフォワードで取得した値を代入 |
④ | XSERVERのMySQLのデータベースに接続するアクセス権所有ユーザーID |
⑤ | アクセス権所有ユーザーIDのパスワード |
⑥ | XSERVERのMySQLのデータベース名 |
⑦ | SSH・ポートフォワーディング関連のクラスをインスタンス |
⑧ | ポートフォワードのホストを代入 |
⑨ | ポートフォワードのポートを代入 |
接続が確立できたら通常のデータベース操作と同様です。
コメント
貴重な情報ありがとうございます。
これまでPuTTYを使う方法しか知らなかったので、大変参考になりました。
これらのクラスを実際に使用してDBにクエリを発行するサンプルコードまであると、もっと喜ぶ人が増える記事だと思いました。