Ubuntu(Lightsailおよびmultipass仮想環境)のMySQLにローカルからSSH経由で接続
Ubuntu(Lightsailおよびmultipass仮想) に Blazor WebAssemblyおよびASP.NET API アプリを構築してデプロイ
デプロイするアプリはMySQLと同じサーバーに置くつもりなので問題ないのだけれど、ローカルPCで動かすにあたっては、multipass上の仮想サーバーやLightsailの中のMySQLにアクセスさせたい。
とはいえ、MySQL用のポートやらを公開はしたくない。ので、プログラムからもローカル開発時はSSH経由でMySQLに接続させる。
https://mysqlconnector.net/tutorials/connect-ssh/
を参考に、SSH経由でMySQLで接続するサンプル。
SSH.NET の参照設定を行う。
using Renci.SshNet; namespace SetlistShare.Dao; /// <summary> /// /// </summary> public class ConnectionHelper { ///<summary>SSH接続</summary> /// <param name="host">ホスト名</param> /// <param name="username">ユーザー名</param> /// <param name="password">パスワード</param> /// <param name="keyFile">秘密鍵ファイル</param> /// <param name="passPhrase">秘密鍵のパスフレーズ</param> /// <param name="port">ポート番号</param> public static (SshClient sshClient, int Port) ConnectSsh( string host, string username, string? password = null, string? keyFile = null, string? passPhrase = null, int port = 22) { if (string.IsNullOrEmpty(password) && string.IsNullOrEmpty(keyFile)) { throw new ArgumentException("Either password or keyFile must be specified."); } var authMethods = new List<AuthenticationMethod>(); if (!string.IsNullOrEmpty(keyFile)) { var key = new PrivateKeyFile(keyFile, passPhrase); authMethods.Add(new PrivateKeyAuthenticationMethod(username, key)); } if (!string.IsNullOrEmpty(password)) { authMethods.Add(new PasswordAuthenticationMethod(username, password)); } var connectionInfo = new ConnectionInfo(host, port, username, authMethods.ToArray()); var sshClient = new SshClient(connectionInfo); sshClient.Connect(); return (sshClient, port); } ///<summary>SSH接続</summary> /// <param name="host">ホスト名</param> /// <param name="username">ユーザー名</param> /// <param name="password">パスワード</param> /// <param name="keyFile">秘密鍵ファイル</param> /// <param name="passPhrase">秘密鍵のパスフレーズ</param> /// <param name="port">ポート番号</param> /// <param name="dbHost">データベースホスト名</param> /// <param name="dbPort">データベースポート番号</param> public static (SshClient sshClient, int Port) ConnectDatabaseViaSsh( string host, string username, string? password = null, string? keyFile = null, string? passPhrase = null, int port = 22, string? dbHost = "localhost", int dbPort = 3306) { var (sshClient, sshPort) = ConnectSsh(host, username, password, keyFile, passPhrase, port); var forwardPort = new ForwardedPortLocal("127.0.0.1", dbHost, (uint)dbPort); sshClient.AddForwardedPort(forwardPort); forwardPort.Start(); return (sshClient, (int) forwardPort.BoundPort); } }
接続の確認
using MySql.Data.MySqlClient; using SetlistShare.Dao; namespace SetlistShare.Test; public class ConnectionHelperTest { [Fact] public void ConnectSshTest() { var (sshclient, port) = ConnectionHelper.ConnectDatabaseViaSsh ( "lightsail.local", "SSHユーザーID", "SSHぱすわーど"); using (sshclient) { var builder = new MySqlConnectionStringBuilder { Server = "127.0.0.1", Port = (uint)port, UserID = "DBユーザーID", Password = "DBパスワード" }; using (var conn = new MySqlConnection(builder.ConnectionString)) { conn.Open(); using (var cmd = new MySqlCommand("SELECT * FROM setlistshare.Person", conn)) { using (var reader = cmd.ExecuteReader()) { var users = new List<dynamic>(); while (reader.Read()) { users.Add( new { Id = reader.GetInt32(0), Name = reader.GetString(1), Email = reader.GetString(2)} ); } users.ForEach(user => Console.WriteLine($"{user}")); } } } } } }
無事データ取得できました。