SSHポートフォワーディング 勉強用に色々試す

#発端
SSHポートフォワーディングを初めて使ったときに何をやっているのか全く意味がわからず混乱したので、自分で環境を作って色々試してみました。
その自分用の備忘録です。自分が取り組んだ時系列に沿って書いたのでポートフォワーディングについては後半ででてきます。

#今回試した環境
ポートフォワーディングを試すために、
実機と仮想サーバーを合わせて３台用意(全部ubuntu)しました。
それぞれ「自宅PC」「踏み台PC」「ターゲットPC」と呼ぶことにします。
（「自宅PC」から「踏み台PC」を中継して「ターゲットPC」にアクセスしたいという感じ）

踏み台PCとターゲットPCはAzure上のVirtualMachineです。この２つは同じネットワークグループに属しています。
ターゲットPCにはグローバルIPを付与しておらず、踏み台PCからだけ接続することができます。
そのため、自宅PCからターゲットPCにアクセスするためには踏み台PCを中継する必要がある状況にしました。

それぞれの設定は以下で、これを基に記述していきます。

| ここでの呼び方       |       ユーザー |    ホスト名,IPアドレス    |
|:-----------------|:------------------:|:------------------:|
| 自宅PC             |              mypc |        localhost        |
| 踏み台PC           |            humidai |       ○○.japaneast.cloudapp.azure.com       |
| ターゲットPC             |              target |        10.1.0.5（グローバルIPは付与せず）       |

#上記環境でやりたいこと
**ターゲットPCにあるファイル（testfile.txt）を自宅PCにコピーしたい。**

```shell:ターゲットPC
target@target-vm:~$ ls
testfile.txt       ← コピーしたいファイル
target@target-vm:~$ cat testfile.txt
targetにあるファイル！！       ← "testfile.txt"の中身
```
しかし自宅PCから直接ターゲットPCに繋ぐことはできないので、
自宅PC→踏み台PC→ターゲットPC
と踏み台PCを経由して接続します。
この過程でポートフォワーディングを試してみます。

#１．ポートフォワーディングを使わずやってみる
ポートフォワーディングやりたいと言っておきながら、
まず比較のために上記をポートフォワーディングを使わないでやってみました。

**1-1.ターゲットPCの"testfile.txt"をscpで踏み台PCにコピー**
以下は自宅PCからsshで踏み台PCに接続して行ったコマンドです。
ターゲットPCから踏み台PCにtestfile.txtをコピーしています。

```shell:踏み台PC
mypc@mypc: ~$ ssh humidai@○○.japaneast.cloudapp.azure.com
~略~
humidai@humidai-vm:~$ ls
humidai@humidai-vm:~$ scp target@10.1.0.5:testfile.txt ./
target@10.1.0.5s password:
testfile.txt                                  100%   34    27.2KB/s   00:00   
humidai@humidai-vm:~$ cat testfile.txt
targetにあるファイル！！
```

**1-2.踏み台PCにコピーした"testfile.txt"をscpで自宅PCにコピー**
1-1と同じことを踏み台PCから自宅PCに対して行えば目的は達成です。

```shell:自宅PC
mypc@mypc: ~$ scp humidai@○○.japaneast.cloudapp.azure.com:testfile.txt ./
humidai@○○.japaneast.cloudapp.azure.coms password:
testfile.txt                                  100%   34     4.0KB/s   00:00    
mypc@mypc: ~$ cat testfile.txt
targetにあるファイル！！
```
こんな感じでターゲットPCから踏み台PCを中継して自宅PCに"testfile.txt"をコピーできました。

ただこの問題として、
踏み台PCにファイルをコピーしなければならない
（後にファイルを消さなきゃいけない、一時的であっても踏み台PCのディスクを使用しなければならない）
というのがあるらしいです（どの程度問題なのかはよく知りませんが）。

#２．sshポートフォワーディングで華麗にコピーする
次に１と同じことをsshポートフォワーディングを使って行ってみます。
ポートフォワーディングでは自宅PCとターゲットPCが直接通信が繋がっているかのように見せるために**トンネルを掘る**という作業を行うらしいです。

以下の作業ではターミナルを２つ使います。
１つの端末で自宅PCとターゲットPCを繋ぐトンネルを作成（トンネルを掘る用の端末）。
もう１つの端末でそのトンネルを使って自宅PCからターゲットPCにSCPを実行します。

**2-1.トンネルを掘る**
自宅PCから踏み台PCに対して`-L`オプションを設定してsshを実行します。

```shell:踏み台PC（端末１）
mypc@mypc: ~$ ssh humidai@○○.japaneast.cloudapp.azure.com -L 55522:10.1.0.5:22
humidai@○○.japaneast.cloudapp.azure.coms password:
humidai@humidai-vm:~$       ← この端末は閉じてはいけない
```

-Lオプションでは以下の設定を記述します。
`-L ローカルのポート番号:リモートのホスト名:リモートのポート番号`
今回の場合だと以下です。
`-L 自宅PCのポート番号:ターゲットPCのホスト名:ターゲットPCのポート番号`

この-Lオプションは、
ローカルホスト（自宅PC）に指定したポート番号（55522）の接続がきたら、
踏み台を経由して、指定したリモート（ターゲットPC）のホスト・ポート（10.1.0.5、22）に転送する
というルールを設定するようです。

**2-2.トンネルを使ってSCPを実行する**
2-1で設定したlocallhostの55522番ポートに対してscpを実行します。

```shell:自宅PC（端末２）
mypc@mypc: ~$ cat testfile.txt
cat: testfile.txt: そのようなファイルやディレクトリはありません
mypc@mypc: ~$ scp -P 55522 target@localhost:/home/target/testfile.txt ./
target@localhosts password:
testfile.txt                                  100%   34     2.4KB/s   00:00    
mypc@mypc: ~$ cat testfile.txt
targetにあるファイル！！
```
自宅PCのシェルからscpを実行するだけでターゲットPCから"testfile.txt"をコピーできました。
SCPの実行は以下の流れです。
①自宅PC（localhost）のポート55522に通信を行う。
②（端末１で掘ったトンネルが有効なら）ポート55522への通信はターゲットPCの22番ポートに転送される
③転送された先でscpで指定されているtargetユーザーの`/home/target/testfile.txt`ファイルを自宅PCにコピーする。


一応上記の手順でポートフォワーディングを使ってターゲットPCにある`testfile.txt`を自宅PCにコピーできました。
この方法は１のポートフォワーディングを使わない手順と比べて、
踏み台サーバー上にデータを残さないのが良いらしいです。
（数ギガのファイルをコピーするとなったら踏み台サーバー上にコピーしなくてよいのがメリットなのはわかるかも）
また、踏み台PCは通信を繋いでいるだけなのでディスクの容量は使わないらしいです（踏み台PCのディスクが一杯でコピーできない問題が起こらない）。

試せたのは良かったけどまだまだ理解が弱いので、
何かわかってきたら追記します。