C#:秘密鍵を使ってSSH接続をしてからリモート先のMySQLに接続して操作を行う
やりたいこと
- C#でコンソールアプリを作成
- SSHに秘密鍵を使って外部のLinuxサーバー(VPS)にアクセスする
- リモート先のMySQL(リモートから見ればLocalhostにあるやつ)にアクセスして操作したい
前提
SSHの秘密鍵はビルド先の直下にある
ex) \bin\Debug\openssh.key もしくは \bin\Release\openssh.key
※既存のid_rsaファイルをコピーして名前変更するだけ。
必要なパッケージ
SSH.NET NuGet Gallery | SSH.NET 2016.1.0
MySql.Data NuGet Gallery | MySql.Data 8.0.12
MySql.Dataのバージョンは各自の状況に合わせる。
(下記のサンプルを検証した際のMySql.Dataのバージョンは6.9.11.0)
サンプル
using Renci.SshNet; using MySql.Data.MySqlClient; using System.Data; public const string LocalHostAddress = "localhost"; // 空いてるポートなら何でも可。(開発端末/実行端末基準の空きポート) public const uint LocalHostPort = 13306; // ipもしくはホスト名 public const string RelayHostAddress = "dev.test"; // sshのポート。(RelayHostAddressでsshのportがどれに充てられているかによる(22だったり10022だったり)) public const int RelayHostPort = 22; // sshでアクセスするユーザー名 public const string SshUser = "sshuser"; // RelayHostAddressにSshUserの値でユーザーが登録されている且つ公開鍵が登録されていることが前提 public const string SshPrivateKeyFileName = "openssh.key"; // SshPrivateKeyFileName(ssh鍵)を作る際に指定したパスワード public const string SshPassword = "pass"; // リモート先のRelayHostAddressに存在するDBなので"127.0.0.1"を設定 public const string DbHostAddress = "127.0.0.1"; // MySQLのポート。 public const uint DbHostPort = 3306; public const string MySqlUser = "root"; // パスワード未指定の場合は"" public const string MySqlPassword = ""; // dbスキーマ名 public const string DbName = "test"; // 検証用に使うテーブル名 public const string TableName = "tbl_test"; public void AccessSshAndMySql() { // Setup Credentials and Server Information // Key Based Authentication (using keys in OpenSSH Format) var ConnNfo = new ConnectionInfo(RelayHostAddress, RelayHostPort, SshUser, new AuthenticationMethod[]{ new PrivateKeyAuthenticationMethod(SshUser,new PrivateKeyFile[]{ new PrivateKeyFile(SshPrivateKeyFileName, SshPassword) }), } ); using (var client = new SshClient(ConnNfo)) { client.Connect(); try { if (!client.IsConnected) { Console.WriteLine("[NG] SSH Connection failed!!"); } // SSHを経由してアクセス元(開発端末)の空きポートからリモート先のMySQLにアクセスできるようにする。 using (var forwardedPortLocal = new ForwardedPortLocal(LocalHostAddress, LocalHostPort, DbHostAddress, DbHostPort)) { client.AddForwardedPort(forwardedPortLocal); try { forwardedPortLocal.Start(); if (!forwardedPortLocal.IsStarted) { Console.WriteLine("[NG] forwardedPortLocal Connection failed!!"); } // MySQL Start (接続先がフォワードポート) var connStr = string.Format( "server={0};port={1};user={2};password={3};database={4};Pooling=False", forwardedPortLocal.BoundHost, forwardedPortLocal.BoundPort, MySqlUser, MySqlPassword, DbName); var sql = "SELECT * FROM " + TableName; using (var connection = new MySqlConnection(connStr)) using (var com = new MySqlCommand(sql, connection)) { connection.Open(); try { var datatable = new DataTable(); var adapter = new MySqlDataAdapter(sql, connection); adapter.Fill(datatable); } catch (Exception) { /*Ignore SQL Error*/ } connection.Close(); } // MySQL End } finally { client.RemoveForwardedPort(forwardedPortLocal); } } } finally { client.Disconnect(); } } }
参考
c# - Connection to MySQL from .NET using SSH.NET Library - Stack Overflow