ProxyCommandを使って多段SSHを実現する

参考1:http://d.hatena.ne.jp/dayflower/20080204/1202457379
参考2:http://cl.pocari.org/2006-09-04-2.html


概要
学内からしかアクセスできない鯖へ研究室の鯖を介してアクセスする
以前WindowsWinSCPを使ってアクセスしたが,今回はUbuntuでアクセスする


ssh_configのProxyCommandディレクティブとncコマンドを使うと実現できる


ProxyCommandについて
よくわからない
中継鯖からアクセスしたい鯖に接続するコマンドを指定するらしい
ただ,標準入力から入力を受け取って,標準出力に出力するようなコマンドじゃないとダメだとか
今回はconnect.cをコンパイルして使用
Perlなどのスクリプト言語でもよさげ

ProxyCommand

サーバへの接続に利用するコマンドを指定します。コマンド文字列は ユーザのシェル環境で実行されます。コマンド文字列の '%h' は接続先のホスト名で置換されます。'%p' はポート番号で置換されます。コマンドは基本的にどのようなものでもかまいませんが,標準入力から入力をうけつけ標準出力に出力するものである必要があります。そして最終的にはどこかのマシンで動いている sshd サーバや inetd 経由の sshd -i に接続する必要があります。通常,接続先のホストの HostName(たいがいユーザがコマンドラインで指定した名前そのものになりますが)を利用して host key 管理を行います。コマンドに「none」と指定すると,この機能は完全に無効になります。ProxyCommand を利用した場合には,CheckHostIP オプションが利用できないことに注意してください。

この設定子は nc(1) とそのプロキシー機能を絡めて利用すると便利です。たとえば下記のような設定をすると 192.0.2.0 の HTTP(S) プロキシを通じて接続することになります:

ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
Manual Pages: ssh_config

SOCKS 経由の通信
OpenSSH には,単体で SOCKS 経由の通信を行う機能はありません.その代わりに,ProxyCommand というオプションを利用して, SOCKS サーバーに接続する外部プログラムを呼び出すことによって通信を行います.

About SSH


nc(netcat)について
指定したホストとのネットワークのやり取りを標準入出力にリダイレクトしてくれる
telnetに似たようなもの?
最近のディストリビューションには標準で入っているらしい
Ubuntuには入っていた
しかし,中継鯖となるSolarisには入っていなかったので,今回は同様の機能を持つconnect.cをコンパイルして利用


connect.cコンパイル
http://www.meadowy.org/~gotoh/ssh/connect.cからソースコードをダウンロード
ソースのコメントを見ながらコンパイル
実行環境がSolarisなので以下を実行

gcc -O2 -o connect -lresolve -lsocket -lnsl connect.c
connect.c: In function `check_direct':
connect.c:1098: error: `INADDR_NONE' undeclared (first use in this function)
connect.c:1098: error: (Each undeclared identifier is reported only once
connect.c:1098: error: for each function it appears in.)

INADDR_NONEが定義されてないぽい
ググってみたら,Solaris10では(Solaris7から?)INADDR_NONEとINADDR_BROADCASTが同じ値っぽい
参考:http://www2s.biglobe.ne.jp/~futot/research/rdesktop.html


と言うわけで,以下をconnect.cに記述

#define INADDR_NONE INADDR_BROADCAST

コンパイル
うまくいったので出来たファイルを中継鯖の~/binに置く


ローカルの設定
~/.ssh/configに以下を追記

Host 「ホスト名」
	ProxyCommand ssh -l 「ユーザ名」 「中継鯖アドレス」 ~/bin/connect %h %p

ちなみに、%hは「ホスト名」に展開される
よって、中継鯖からみて接続したい鯖が「ホスト名」で名前解決できないといけない
「ホスト名」を適当につけてアクセスしたい場合は%hを中継鯖から見た「接続したい鯖のアドレス」にしてやる
あとは,Ubuntuの「サーバへ接続」で

  • サービスの種類:SSH
  • サーバ名:「ホスト名」
  • ポート番号:22
  • あとは適当に設定
  • 接続

これで透過的に非公開鯖にアクセスできる
もちろん

ssh 「ホスト名」

でも,アクセスできる