ssh portfowarding

//paintくんに教えていただきました。

sshで、「自分(localhost)のX番ポートを、A(hostA)さんを踏み台にして、B(hostB)さんのY番ポートに直結する」には、

ssh -L X:hostB:Y -l usernameA hostA

とする。
イメージとしては、
「普通にhostAにsshでログインする(だからusernameはAに対してのもの)。」
「その際、localhostのX番ポートに投げ込んだ通信を、hostBのY番ポートに対して送りつけるようにお願いする。」
という感じ。
だから、hostAまでの間は暗号化通信だけれども、hostB:Yに投げつけるパケットは暗号化されていない。

自分のポートと相手先のポートを暗号化してつなぐ

これは、ftpやブラウザなど(sshのポート番号22以外を使っている)の経路を暗号化するのに有効。

ssh -L X:hostA:Y -l usernameA hostA

こうすれば、自分のX番ポートが直接hostAのY番ポートにつながる。
無駄足だが、例えばscpは、
・自分の側(localhost)のポート番号は自分で設定できる(-P X)
・相手側(hostA)のポート番号は22番しかダメ(22番で待ち受けているため)
ので、以下のようにすれば暗号化された通信経路でファイルを転送できる。

ssh -L X:hostA:22 -l usernameA hostA //hostAの22番ポートとlocalhostのX番ポートを繋いだ
scp -P X file_to_send usernameA@localhost:~/destination_dir //-Pオプションでポート番号が指定できる。

(もちろん、こんなの使わなくてもscpは暗号化した通信が出来る。単に例である。)

二段階のssh

相手先LANの中にあるマシン(hostB)に対して、中継マシン(hostA)を踏み台にしてsshで入る方法。

ssh -L X:hostB:22 -l usernameA hostA //hostAに入って、localhost:X番ポートとhostB:22番ポートとを繋ぐ。
//22番ポートはsshのlisteningなので、これ以外を指定するとhostBのsshで無いやつらにパケットを送りつけることになる。意味ない。
ssh -p X localhost -l usernameB //すでにhostBの22番ポートとlocalhostのX番ポートがつながっているので、localhostのX番ポートに対してsshをすればそれで入れる。

これだと、すべての経路が暗号化されている。(一行目ですでにlocalhost:XがhostB:22につながってはいるのだけれど、その間は暗号化されていない。なのでもう一段暗号化が欲しい。)

scpを中継マシン越しに行う

このあたりから実用的になってくる。
scpも22番ポートを使うので、二段階sshとほぼ同じになる。

ssh -L X:hostB:22 -l usernameA hostA //hostAに入って、localhost:XのポートとhostB:22ポートを繋ぐ。
scp file_to_send -P X usernameA@hostA:~/destination_dir //-Pでポートの指定が出来る。localhostのX番ポート(=hostB:22)に対して暗号化したファイルを転送している。

などとすれば良い。

一般的なcommandについて、その経路を暗号化する

まずは中継マシン無しのバージョン。
この場合、commandがどのポートを使うか事前に知っておかなくてはいけない。
ここでは、localhostからの送信にX、hostAの受信にYを使っているとしておく。

ssh -L X:hostA:Y -l usernameA hostA //hostAに入って、localhost:XのポートとhostB:Yを繋ぐ。
command ・・・・ //コマンドを実行する。

これで、commandによるlocalhost:Xに対する書き込みがすべて暗号化された上で、hostA:Yに送りつけられる。

一般的なcommandについて、その経路を暗号化する(2段階sshバージョン)

中継マシンを通して、一般的なコマンドを実行するための方法。
いくつか方法は考えられるが、対称性の観点から美しいのは次のようなもの。

localhost:XからhostA:Zに繋ぎ、hostA:ZからhostB:Yに繋ぐ。
この時、commandは、localhostからの送信にX、hostBでの受信にYのポートを使っていることにしておく。Zは任意のポート。

ssh -L X:hostA:Z -l usernameA hostA //まずはlocalhost:XとhostA:Zを繋ぐ。自動的にshellはhostAの中のものに移る。
ssh -L Z:hostB:Y -l usernameB hostB //つぎにhostA:Z(今はshellがhostAに移っているので、これがlocalhostに相当している。)をhostB:Yに繋ぐ。
//新しいshellで、
commmand ・・・ //localhost:Xに投げ込んだパケットは、hostB:Yに送りつけられる。

こうすると、すべての経路が暗号化される。


/////特に試すわけでもなく適当に書いたので間違ってたらゴメンなさい。