1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RubyでSSHサーバーを立てる

Last updated at Posted at 2018-05-26

RubyでSSHサーバーを立ててみます。

使うのは、hrr_rb_ssh Gem(現時点で、バージョンは0.4.0)です。

使いどころ

  • SSH接続を利用するツール等のテストに
  • ネットワーク機器等のシミュレーターとして
  • SSH Subsystemの実装に(NETCONF等)
  • ユーザー権限で動かすオレオレSSHサーバーとして

インストール

Gemは、次のようにインストールします。

Bundlerを使う場合、

Gemfile
gem 'hrr_rb_ssh'
gem 'hrr_rb_ssh-ed25519' # ed25519を使う場合

というファイルを作り、

$ bundle install

します。もしくは、直接

$ gem install hrr_rb_ssh
$ gem install hrr_rb_ssh-ed25519 # ed25519を使う場合

を実行します。

使ってみる

まずは、実行ユーザーのシェルにログインできるSSHサーバーを立ててみます。

ちょっと長いですが、やっていることは、

  • ライブラリを読み込む
  • 認証(publickey、password)情報の定義
  • SSH内部処理のハンドラの定義(実際には、デフォルト実装を使用)
  • TCPserverを立てて、接続を待ち受ける
  • SSHサーバーサービスを開始する

です。

require 'logger'
require 'socket'
require 'hrr_rb_ssh'
require 'hrr_rb_ssh/ed25519' # ed25519を使う場合


logger = Logger.new STDOUT
logger.level = Logger::INFO


# 公開鍵認証に、OpenSSHの~/.ssh/authorized_keysを使う
auth_publickey = HrrRbSsh::Authentication::Authenticator.new { |context|
  username = ENV['USER']
  homedir = Dir.home
  authorized_keys = HrrRbSsh::Compat::OpenSSH::AuthorizedKeys.new(File.read(File.join(homedir, '.ssh', 'authorized_keys')))
  authorized_keys.any?{ |public_key|
    context.verify username, public_key.algorithm_name, public_key.to_pem
  }
}
# 指定のパスワードで認証する
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
  username = ENV['USER']
  password = '接続時に使うパスワード'
  context.verify username, password
}


options = {}

# 定義した認証を利用する
options['authentication_publickey_authenticator'] = auth_publickey
options['authentication_password_authenticator']  = auth_password

# SSH接続の内部処理を、デフォルト実装のハンドラで処理する
options['connection_channel_request_pty_req']       = HrrRbSsh::Connection::RequestHandler::ReferencePtyReqRequestHandler.new
options['connection_channel_request_env']           = HrrRbSsh::Connection::RequestHandler::ReferenceEnvRequestHandler.new
options['connection_channel_request_shell']         = HrrRbSsh::Connection::RequestHandler::ReferenceShellRequestHandler.new
options['connection_channel_request_exec']          = HrrRbSsh::Connection::RequestHandler::ReferenceExecRequestHandler.new
options['connection_channel_request_window_change'] = HrrRbSsh::Connection::RequestHandler::ReferenceWindowChangeRequestHandler.new


# ポート10022番で接続を待ち受ける
server = TCPServer.new 10022
io = server.accept

# SSHサーバーを起動する
server = HrrRbSsh::Server.new options, logger: logger
server.start io

独自サービスを提供する

使ってみる では、デフォルトのハンドラを利用し、ユーザーのログインシェルをサービスとして提供しました。

ここでは、ログインシェルの代わりに、独自サービスとして、echoサーバー(処理は何も行わず、ただ文字をエコーバックするだけ)を実装してみます。

コードは、次のようになります。

require 'logger'
require 'socket'
require 'hrr_rb_ssh'
require 'hrr_rb_ssh/ed25519' # ed25519を使う場合


logger = Logger.new STDOUT
logger.level = Logger::INFO


# 指定のパスワードで認証する
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
  username = ENV['USER']
  password = '接続時に使うパスワード'
  context.verify username, password
}


# echoサーバーの処理を実装
conn_echo = HrrRbSsh::Connection::RequestHandler.new { |context|
  context.chain_proc { |chain|
    # SSHクライアントに、最初のメッセージを出力(context.io[1].write)する
    context.io[1].write "Start echo service\r\n"
    loop do
      # SSHクライアントからの入力(context.io[0].read)を受けて
      buf = context.io[0].readpartial(10240)
      # Ctrl+Dが入力された場合、抜ける
      break if buf.include?(0x04.chr)
      # SSHクライアントに出力(context.io[1].write)する
      context.io[1].write buf
    end
    exitstatus = 0 
    exitstatus
  } 
} 


options = {}

# 定義した認証を利用する
options['authentication_publickey_authenticator'] = auth_publickey
options['authentication_password_authenticator']  = auth_password

# shellのリクエストに対するハンドラを、echoサーバーの実装に置き換える
options['connection_channel_request_shell'] = conn_echo


# ポート10022番で接続を待ち受ける
server = TCPServer.new 10022
io = server.accept

# SSHサーバーを起動する
server = HrrRbSsh::Server.new options, logger: logger
server.start io

SSHクライアントからアクセスし、例えば foobarbaz... と入力すると、

$ ssh localhost -p 10022
Password: 接続時に使うパスワード
Start echo service
foobarbaz...

のように、入力がエコーバックされます。

このように、HrrRbSsh::Connection::RequestHandler.new {|context| ...} を定義することで、独自のサービスを提供することが可能になります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?