Firefoxからsshのダイナミック転送を使って非公開サーバへアクセスする

 sshにはダイナミック転送という機能がある。この機能を使うと、sshはアプリケーション側にはSOCKSプロクシとして振る舞うが、そこからsshの接続先までは暗号化された状態で通信が行われる。
 これだけだと通常のトンネリングとどう違うのかよくわからないかもしれないが、ダイナミック転送の場合は転送ポートを指定する必要がない。ここがダイナミックと表現される所以だろう。
 例えば、オフィスAにある開発サーバdev1にオフィス外からアクセスしたいとする。しかし、dev1はオフィス外には公開されておらず、踏み台サーバladd1を経由してしかアクセスするしかない。ladd1はsshのみが動いており、これまではsshのトンネリング機能を使ってアクセスしてきたのだが、ウェブアプリケーションデバッグする際はいちいちウェブアプリケーションのポート毎にトンネルを掘るのが面倒くさい。オフィスに限らずデータセンターへのアクセスなどでも同様の問題はよく見られる。こういう際にダイナミック転送が使える。
 まず前提条件として、基本的に、使いたいアプリケーションはSOCKSプロキシに対応していた方が良い。(無理やり全部の通信をプロキシ経由にしてしまうプログラムはあるので、必須ではない。)幸い、Firefox, IE, Google Chromeあたりのブラウザは全部SOCKSプロキシに対応している。今回はFirefoxを使う。
 まず、sshでダイナミック転送を行うトンネルを掘る。これは非常に簡単で、

ssh -D portnum ladd1

 とするとだけで良い。-DはDynamicの意である。portnumは適当な数値で良いが、SOCKSのポート番号は1080番が一般的らしいので、使えるならば1080にしておくと良さそう。
 次に、Firefox側の設定に移る。FirefoxにはProxy auto-configという機能があり、JavaScriptでどのホストへのアクセスをどのサーバ経由で行うか、ということをカスタマイズできる。今回の例だと、以下のようなJavaScriptになる。

function FindProxyForURL(url, host)
{
  if (host == "dev1") {
    return "SOCKS5 127.0.0.1:portnum";
  }
  return "DIRECT";
}

 これを、proxy.pacとかそんな名前をつけて保存する。dev1とportnumのあたりは自分の環境に合わせてカスタマイズする必要がある。urlとhostが引数に渡されてくるので、これを使ってかなり自由にプロクシサーバの設定ができるのだが、面倒くさいし調べれば豊富に情報が見つかるので省略。FindProxyForURLとかで検索するとよいです。
 ポイントはSOCKS5と書くところで、これによってプロクシサーバとのプロトコルがSOCKS5であることを指定している。単にSOCKSと書いただけじゃうまく通信してくれない(たぶんSOCKS4になってるんじゃないかと思う)から注意すること。この情報が日本語で見つからなかったのが、今このエントリを書いている主要因である。

 proxy.pacができたら、Firefoxがこれを使うように指定する。まず、設定画面から「詳細」→「ネットワーク」→「接続設定」でプロキシの設定画面を開く。設定はたぶん「プロキシを使用しない」になっているので、「自動プロキシ設定スクリプトURL」に変更し、ファイル名を入力する。URLとなっているし、ファイル選択ダイアログもないのだが、ファイル名を入力するとそれを使ってくれる。ただし、ファイル名がfile:///で始まることに注意する必要がある。スラッシュの数が3つであることに注意。Linuxとかだと「file:///home/tkng/proxy.pac」という感じで設定できる。Windowsの場合、スラッシュの数がどうなるのかはよくわからない。試行錯誤が必要かもしれない。
 すべてがうまくいけば、Firefoxのロケーションバーにhttp://dev1/と打ち込むと、ladd1経由でdev1へとアクセスできる。http://dev1:3000/とか、ポート番号も自由に変更できる。名前解決に失敗する場合は、network.proxy.socks_remote_dnsの設定をtrueに変更するとよいだろう。
 これまでは勝手知ったる普通のトンネリングでなんとか対処していたのだけれど、一回ダイナミック転送を使うと、もう普通のトンネリングには戻る気が起きない。ちょっとした手間の差でしかないんだけど、これは便利だ。
 以下追記:

  • 読み返すとどこがダイナミック転送の魅力なのかよくわからなかったので、改めて説明しておきます。一番魅力的なのは、サーバ名によってプロクシの使用についてカスタマイズができる点で、これによって以下のようなメリットが得られます。この3つが全部成立する手法は、今のところダイナミック転送+Proxy auto-configの組み合わせしか知らない。
    • いちいちlocalhostの特定のポートにトンネリングをする手間が省ける。今ローカルマシンのどのポートにどのサーバの何番のポートを転送しているのか、マッピングをいちいち記憶していると割とストレスがたまる。
    • 見たいポートが増える度にいちいちトンネルを掘らなくてよい。デバッグ時は別ポートでテストサーバを立てたりしたいので、その結果がすぐにブラウザで確認できるとうれしい。
    • サーバ名によってどのプロクシを使うのかが切り替えられる。つまり、2つ以上のプロクシを同時に使用することができる。
  • ブクマコメントでid:hogemさんがGoogle ChromeのSOCKS対応を疑問視されていましたが、調べてみましたらGoogle ChromeはまだSOCKSプロキシに対応してませんでした。Google Summmer of Code 2009で開発予定だそうです