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}"));
}
}
}
}
}
}
無事データ取得できました。

