ssh port forwarding
ssh でのポートフォワーディングを勉強したのでまとめます。正確には TCP ポートフォワーディングと言うらしい。以下、単にポートフォワーディングと記載します。
記述に間違い等ありましたらご指摘頂ければ有難いです。
※以降、文体変わります
基礎概念
概念的には、マシンAのポートをトンネルの入り口とし、出口をマシンBのポートにするという絵をイメージするとよい。まずは難しく考えず、この絵だけを想像しておく。トンネルの中を通信が通過する。
マシンAとマシンBに ssh で接続を作っておく。これがトンネルになる。トンネルには、予め入り口と出口、ならびに出口の先の終着点をを設定する。これはトンネル構築時に行う(基本的には。応用は後述)。
出口はマシンBのポートなので、マシンBの環境から接続できる先が終着点となる。仮にマシンCとする。終着点には当然ながらポートも指定する。
マシンAのポート 9999 を入り口とし、マシンBが出口。マシンCのポート10000 が終着点としてトンネルを構築。するとマシンAの9999に接続するとマシンCのポートにつながることになる。
マシンAとマシンBの間は ssh の機能により暗号化され安全になる。ただし、マシンBとマシンCの間は暗号化されないし、マシンAに到達するまでの通信も暗号化されない。
以下では OpenSSH 4.3p2 での利用法をを主に示す。
利用方法
のっけから余談だが、以下の例では一部に -C オプションをつけた状態でコマンド例を記載する。-Cオプションの意味は後述。例を読む上では無視してよい。
例1 ローカルからのポートフォワーディング
ssh -C -L [bind_address:]in_port:goal_host:goal_port [user@]out_host
-L オプションがローカルからのポートフォワーディングの指定。
このコマンドを実行したホストが入り口となる。先の例ではマシンA。
in_port が入り口ポート。bind_addressを指定した場合、そのアドレスで listenする。デフォルトは127.0.0.1。
out_host がトンネルの出口になるマシン。先の例ではマシンBに相当する。
goal_host と goal_port が終着点。先の例では マシンC。
よって、この例では bind_address:in_port に接続すると、その通信は暗号化された状態で out_host へ転送され、復号されたうえで out_host からgoal_host:goal_port に渡される。bind_address:in_port に接続した側から見れば、最初から goal_host:goal_port に接続したのと同等の効果を得られる。
例2 リモートからのポートフォワーディング
ssh -C -R [bind_address:]in_port:goal_host:goal_port [user@]in_host
-R オプションがリモートからのポートフォワーディングの指定。
このコマンドを実行したホストが出口となる。
少々ややこしいが、このコマンドを実行する側から見れば in_host がリモートホストである。in_host で in_port が listen される。つまり、リモートホストが入り口 ― ホストA になる。
出口であるホストBはこのコマンドを打ったマシンとなる。
終着点は変わらず goal_host:goal_port である。
この場合の bind_address がどのような挙動を示すかは確認できなかった。
制限方法
(2008/09/02 追記:現在のところ、決め手となる対策が見当たらないようだ)
sshd_config の AllowTcpForwarding
ポートフォワーディングされる事を制限するには /etc/ssh/sshd_config のAllowTcpForwarding パラメータを no に設定する。
AllowTcpForwarding no
検証した結果、この設定の挙動には幾つかのパターンがある。尚、手元に環境がなかったため、入り口側ホストと出口側ホストの OpenSSH のバージョンに差異がある状態での確認となっている。
- | 入口側ホストのAllowTcpForwarding | 出口側ホストのAllowTcpForwarding | 結果 |
---|---|---|---|
ローカルからのポートフォワーディング | yes | no | 出口から終着点への接続が拒否される |
no | yes | 制限されない | |
リモートからのポートフォワーディング | yes | no | 制限されない |
no | yes | ポートの Listen が制限される |
確認した限り直感的な挙動ではないし、統一的に制限できる訳でもないようだ。
さらに man にも書いてあるが、シェルアクセスできる以上、そのユーザは転送のためのプログラムを配置できるので完全な制約とはならない。
その他
- -C オプションを併用すれば通信が圧縮されるのでトラフィックを節約できる。