特定のサーバを踏み台にして別のsshサーバに接続する (ProxyCommand)

2010-01-21 23:08 | tag:

インターネット上のサーバのsshdの設定で、接続できるホストのIPアドレスを限定するという運用は多いと思います。このような運用を行っている場合、目的のサーバに接続するためには、以下のように一旦プロキシ(踏み台)サーバに接続して、あらためて目的のサーバに接続するという操作となり、やや煩雑です。

■概念図

|クライアント| --(ssh)--> |プロキシサーバ| --(ssh)--> |目的のサーバ|

■手順

1. クライアントからプロキシサーバに対してsshで接続、ログイン。
   (user_proxyはプロキシサーバ上のユーザー)

   $ ssh user_proxy@proxy.example.jp

2. プロキシサーバからクライアントに対してsshで接続、ログイン。
   (user_destは目的のサーバ上のユーザー)

   $ ssh user_dest@dest.example.jp

クライアント上のsshクライアント設定で ProxyCommand の設定を行うと、このような二段階の操作ではなく、以下のようにあたかもクライアントから直接目的のサーバに接続しているかのように接続することができます。

■sshのProxyCommandを設定した場合の接続手順

クライアント上で目的のサーバのユーザー・ホスト名を指定して接続、ログイン

$ ssh user_dest@dest.example.jp

※直接dest.example.jpに接続しているように見えるが、実際の通信はプロキシサーバを経由して行われている。

設定手順

クライアントの ~/.ssh/config に以下のような設定を追加します。

Host dest.example.jp
	ProxyCommand ssh user_proxy@proxy.example.jp nc %h %p
  • Hostの後にはプロキシ経由で接続するサーバのホスト名を記述します。"*.example.jp"のように記述すると、example.jpドメインの全てのサーバが対象になります。
  • ProxyCommandの後には、Hostの後に記述したサーバ(この例では dest.example.jp)にクライアントから接続しようとした際に、クライアント上で実行するコマンドを指定します。
  • %hは、クライアントのsshコマンドの引数として渡したホスト名が展開されます。%pは、ポート番号が展開されます。
  • プロキシサーバ(proxy.example.jp)上にはncコマンドが必要です。CentOSの場合は yum install nc でインストールできます。

動作原理

sshコマンドで~/.ssh/configのHostに記述したホスト名に一致するサーバに接続しようとすると、通常の接続動作を行う代わりにProxyCommandで指定したコマンドが実行されます。このとき、%hは接続先ホスト名、%pは接続先ポート番号が展開されます。

前述の設定例の場合の、ユーザーが入力するコマンドと実際にクライアントのsshコマンドの裏で実行されるコマンドの関係は次の通りです。

入力するコマンド ssh user_dest@dest.example.jp
裏で実行されるコマンド ssh user_proxy@proxy.example.jp nc dest.example.jp 22

「裏で実行されるコマンド」の動作は次の通りです。

  • ホスト"proxy.example.jp"にsshで接続
  • ホスト"proxy.example.jp"上で"nc dest.example.jp 22"を実行

クライアント上のsshコマンドは、本来はネットワークを介して接続先のサーバとやりとりするはずの通信内容を裏で実行したコマンドに標準入出力経由で渡します。

一方、プロキシサーバ"proxy.example.jp"上で実行されるncは、ホスト名・ポート番号で指定された先に接続し、標準入力で受け取った内容を接続先に送出、接続先から受け取った内容を標準出力に出力します。

裏で実行されたsshコマンドがクライアント上で実行されたsshコマンドとプロキシサーバ上で実行されたncコマンドの入出力をつなぐことにより、プロキシサーバを経由した目的サーバへの接続が実現します。

この設定が必要になった経緯

自宅のインターネット回線を、Bフレッツマンション(プロバイダはASAHIネット)からエネルギアコミュニケーションズのMEGA EGGに切り替えました。

ASAHIネットでは固定グローバルIPアドレスを利用していたので、各サーバへのsshでの接続はそのIPアドレスを指定して制限していましたが、エネルギアコミュニケーションズには安価な固定グローバルIPアドレスのサービスはありません。

単にサーバのメンテナンスをするだけの目的であれば二段階での接続でもなんとかなります。しかし、webサイトの更新をssh経由でのrsyncで行っていた関係上、クライアントからプロキシサーバの存在を意識せずに目的のサーバに接続できる環境がどうしても必要でした。これが実現できないと、webサイトのコンテンツを一旦プロキシサーバに転送してから改めて目的のサーバに転送するという操作が必要になり、あまりにも煩雑でとても耐えられないと考えました。

参考にした情報