본문 바로가기
개발/ASP.NET

C# private key로 SSH 접속 후 리모트 내의 MySQL에 접속해서 DB 조작 하기

by ispie 2019. 1. 28.

하고 싶은 것

  • C#으로 콘솔 응용 어플을 작성 할 예정
  • 외부에 있는 Linux 서버(VPS)에 private key로 SSH 접속해서 이것 저것 만지고 싶다
  • 리모트 측의 MySQL(해당 서버 입장에서 보면 Localhost)에 접속해서 DB를 조작하고 싶다

 


전제 조건

 

SSH의 private key는 빌드한 폴더에 격납합니다.


ex) \bin\Debug\openssh.key 또는 \bin\Release\openssh.key

 


※기본의 id_rsa(private key)파일을 카피해서 openssh.key로 이름을 변경 하였습니다.

 


필요한 패키지


SSH.NET
https://www.nuget.org/packages/SSH.NET/

MySql.Data
https://www.nuget.org/packages/MySql.Data/

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"; 

// private key의 설정. RelayHostAddress(운용단말)에 SshUser로 유저 등록이 되어 있고, 공개키가 등록되어 있는것이 전제
public const string SshPrivateKeyFileName = "openssh.key";

// SshPrivateKeyFileName(ssh키)를 만들 시에 지정한 패스워드
public const string SshPassword = "pass"; 

// DB의 호스트 어드레스. 리모트 접속처인 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를 경유해서 개발단말(운용단말에 접속하러 갈 PC)의 미사용 포트 번호를 이용해서 운용단말에 있는 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();
		}
	}
}

 

 

참고 사이트

Connection to MySQL from .NET using SSH.NET Library

SSHホストを介してMySQLへ接続

 

 

추가

만약에 위의 내용을 작업시에 MySQL Workbench 로 SSH경유의 DB에 접속해서 값을 확인하고 싶을 경우에는 Connectin Method [Standard TCP/IP over SSH] 를 선택 후 SSH Key File 경로에 주의해서 설정하면 문제 없이 접속 가능합니다.

 

 

 

 

댓글