ssh_config2009/05/15

前置き

先日のエントリで少し触れたけれど、 Net::SSHでは、ログイン時にssh_configを適用することができます。

CapistranoのSSHログイン(ローカルからターゲットにログインする経路)もNet::SSHによるものなので、 同様に適用されます。

APP_ROOT/config/deploy.rb で

set :ssh_options, {:key => value}

に指定した Hash が、

Net::SSH.start(host, username, options={})

の options に与えられます。

今回の目標

ファイアウォールの先にあるホストへ Capistrano を使用して Railsプロジェクトを Deploy できる設定を目指します。

図にするとこんな感じです。

自社 ------------> <--WAN--> <------ ターゲット
+---------+  +------+     +----+  +----------+
|localhost|--|自社GW|--x--| GW |--|ターゲット|
+---------+  +------+     +----+  +----------+

具体的には、

# ssh (ターゲットのホスト名)

一発でログインできる環境が構築できれば成功です。

ssh_config

ssh_configは

~/.ssh/config
/etc/ssh/ssh_config

がデフォルトで参照されます。 優先順位は

コマンドラインオプション
      ↓
~/.ssh/config
      ↓
/etc/ssh/ssh_config

の順。 今回のような目的であれば、~/.ssh/config を編集するべきでしょう。

先程の図の場合、localhostから一発で ターゲットに接続するために必要な設定は

Host target-host.example.com
  User target-user
  ProxyCommand ssh gateway-host.example.com nc target-host.local.example.com %p
Host gateway-host.example.com
  User gateway-user

となります。

この状態で、

# ssh target-host.example.com

を実行すると、ゲートウェイに対する認証、ターゲットに対する認証を行なった上で (このあたりはそれぞれデフォルトが使われています。必要なら IdentityFile の設定を追加してください) ターゲットにログインできるはずです。

設定を順に説明すると

Host (ホスト名)

次にこの指定が出現するまでの間の設定は (ホスト名) が指定された接続の際にのみ利用されます。

(ホスト名)は任意の文字列で、実際のホスト名やIPアドレスと一致している必要はありません。 (後述のProxyCommandなどで上書きしておかないと、実在しないホスト名は当然接続に失敗しますが……)

sshコマンド等で接続するさいに、ホスト名として指定した文字列と一致する必要があります。 文字列としての一致が必要なので、ssh_config にIPアドレスで記述し、sshコマンドでFQDNを指定した場合、 たとえそれらが同じホストを差す場合でもssh_configの設定は適用されません。

'*'が全てのホストに合致するなど、いくつかのパターンを指定することができます。

パターンの適用により、あるホスト名が複数の Host に合致した場合は、それら全ての設定が適用されます。 設定項目が衝突した場合は、パターンを含まない Host で指定した項目が優先されます。 (パターンを含む Host 同士で衝突があった場合の挙動は不明)

User (ユーザ名)

sshでログインする際のユーザ名です。 sshコマンドの-lオプションと等価。

(オプションで上書きされます)

ProxyCommand (command)

今回のキモ

# ssh (ホスト名)

を実行したときに、実際に実行されるコマンドです。

%p ポート番号
%h ホスト名

に置換されます。

ProxyCommand ssh gateway-host nc target-host %p

の場合だと、ユーザが

# ssh target-host

を実行しようとした場合、実際には gateway-host に接続を行い、その接続の上でnc(netcat)で target-host に接続を行っていることになります。 結果として、ローカルのコンソールは target-host に接続される訳です。

この時、この ssh コマンドに対しても ssh_config は適用されるので、gateway-hostへの接続については

Host gateway-host
  User gateway-user

ここで指定したユーザ名が使われることになります。

更に応用すると、

Host target-host.example.com
  User target-user
  ProxyCommand ssh gateway2-host.local.example.com nc target-host.local.example.com %p
Host gateway2-host.local.example.com
  User gateway2-user
  ProxyCommand ssh gateway-host.example.com nc gateway2-host.local.example.com %p
Host gateway-host.example.com
  User gateway-user

こんな感じで、ゲートウェイを多段で越えることもできます。