概要

SSH (Secure Shell) は、ネットワーク上の別のコンピュータにリモートでアクセスするための暗号化されたプロトコルである。

主に以下の3つの機能がある。

  • リモートログイン
    別のコンピュータにログインして、コマンドラインからファイル操作やプログラムの実行等ができる。
  • ファイル転送
    SCPまたはSFTPというプロトコルを使用してて、安全にファイルを転送できる。
  • X11フォワーディング
    X Window Systemのグラフィカルな出力をリモートで表示することができる。


SSHは従来のTelnetやFTP等の非暗号化プロトコルと比較して、通信内容が盗聴から守られるため、セキュリティが高いのが大きな利点である。
また、公開鍵暗号方式を用いた認証では、パスワードを明示的に送る必要が無い。

UNIXシステムでは標準でSSHサーバが含まれており、WindowsでもサードパーティーのSSHクライアント / サーバが利用できる。
多くのクラウドサービスやネットワーク機器でもSSHによるリモート管理を行うことができる。

C#において使用できるSSHライブラリとして、SSH.NET等がある。



処理の流れ

  1. SshClientクラスのインスタンスを生成して、ホスト、ユーザ名、パスワードを指定する。
  2. Connectメソッドを使用して、リモートPCへの接続を確立する。
  3. RunCommandメソッドを使用して、コマンドを実行する。
    Resultプロパティで出力を取得することができる。
  4. Executeメソッドを使用してコマンドを実行することにより、終了コードを取得することができる。


SSH.NETには他にも様々な機能があり、ファイル転送、SFTPサポート、ポートフォワーディング等ができる。


リモートPCでコマンドを実行

 using Renci.SshNet;

 class Program
 {
    static void Main(string[] args)
    {
       using (var client = new SshClient("<リモートPCのIPアドレス または ホスト名>",
                                         "<リモートPCのユーザ名>",
                                         "<リモートPCのユーザ名のパスワード>"))
       {
          client.Connect();
 
          // リモートPC上で"ls -l"コマンドを実行する
          var cmd = client.RunCommand("ls -l");
          Console.WriteLine(cmd.Result);
 
          // リモートPC上で"mkdir tmpdir"コマンドを実行する
          var result = client.RunCommand("mkdir tmpdir").Execute();
          Console.WriteLine("Exit code: {0}", result);
       }
    }
 }



ポートフォワーディング

SSH.NETには、ポートフォワーディングの機能が組み込まれており、
ForwardedPortLocalクラスを使用してローカルポートフォワーディングを実装することができる。

ポートフォワーディングが使用される理由としては、リモートPCにSSHで直接接続できない場合に別のホストを経由して接続するためである。

以下の例では、ローカルPCの50022番ポートからリモートPCの22番ポートへの接続を転送している。

  • portForwarded.Startメソッドを使用して、ポートフォワーディングを開始する。
  • portForwarded.Stopメソッドを使用して、ポートフォワーディングを停止する。


ただし、リモートPCの設定によっては、ポートフォワーディングができない場合もあるので注意が必要となる。

 using Renci.SshNet;
 using Renci.SshNet.Common;
 
 class Program
 {
    static void Main(string[] args)
    {
       using (var client = new SshClient("<リモートPCのIPアドレス または ホスト名>",
                                         "<リモートPCのユーザ名>",
                                         "<リモートPCのユーザ名のパスワード>"))
       {
          client.Connect();
 
          var portForwarded = new ForwardedPortLocal("<ホストPCのIPアドレス または ホスト名>", 50022,
                                                     "<リモートPCのIPアドレス または ホスト名>", 22);
          client.AddForwardedPort(portForwarded);
          portForwarded.Exception += PortForwarded_Exception;
          portForwarded.Start();
 
          using (var cmd = client.CreateCommand("ls -l"))
          {
             var result = cmd.Execute();
             Console.WriteLine("Command output: {0}", result);
          }
 
          portForwarded.Stop();
       }
    }
 
    private static void PortForwarded_Exception(object sender, ExceptionEventArgs e)
    {
       Console.WriteLine($"Port forwarded exception: {e.Exception.Message}");
    }
 }