IT業界のすみっこ暮らし

ふと気がついたときの記録

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();
        }
    }
}

参考

のぶろぐ SSHホストを介してMySQLへ接続

c# - Connection to MySQL from .NET using SSH.NET Library - Stack Overflow



プライバシーポリシー