SSHダイナミックポートフォワーディングについて知識整理してみた

## はじめに
前回の記事に続きまして、今回はSSHダイナミックポートフォワーディングについてまとめてみました。
あくまで、自分の認識なので間違っている箇所があれば教えていただけると助かります。

## SSHダイナミックポートフォワーディング
ダイナミックポートフォワーディングのコマンドは以下のようになります。

```
ssh -D <クライアントPCのポート> <SSH接続先サーバのユーザ名>@<SSH接続先サーバのIP>
```

ダイナミックポートフォワーディングと通常のポートフォワーディングの違いは、**SSH接続先のサーバがあるネットワーク内のサーバであれば、どれでも自由にアクセスできること**です。  
通常のポートフォワーディングでは、コマンドの段階で最終的にアクセスするサーバを決めていましたが、ダイナミックポートフォワーディングではその指定がありません。  
上記のコマンドを実行すれば、リモートネットワーク内のサーバであればどれでも自由にアクセスできるようになります。

:::note warn
補足で説明しますが、事前設定が必要な場合や対応していないアプリケーションもあるのでご注意ください。
:::



### -D オプション
ダイナミックポートフォワーディングをする際には、コマンドで`-D`オプションを指定します。  
`man ssh`で表示される`-D`オプションの説明は以下のようになります。

>Specifies a local “dynamic” application-level port forwarding.  This works by allocating a socket to listen to port on the local side, optionally bound to the specified bind_address.  Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine.  Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will act as a SOCKS server.  Only root can forward privileged ports.  Dynamic port forwardings can also be specified in the configuration file.
>  
>IPv6 addresses can be specified by enclosing the address in square brackets.  Only the superuser can forward privileged ports.  By default, the local port is bound in accordance with the GatewayPorts setting.  However, an explicit bind_address may be used to bind the connection to a specific address.  The bind_address of “localhost” indicates that the listening port be bound for local use only, while an empty address or ‘*’ indicates that the port should be available from all interfaces.


自分なりに重要そうな部分をまとめると、
- 動的なアプリケーションレベルのポートフォワーディングをする際に使用するオプション
- ローカル側のリッスンポートを指定する必要がある（これがSSHトンネルの入口になる）
- 指定したリッスンポートへの接続が確立されると、セキュアなチャネルを介してSSH接続先サーバへ転送される
- ダイナミックポートフォワーディングにおいて、SSHはSOCKSサーバとしての役割になる
- SSHが現在サポートしてるSOCKSのバージョンは、SOCKS4とSOCKS5の二つ

となります。

### SOCKS
`-D`オプションの説明では**SOCKS**という単語が出てきました。  
これは通信プロトコルの一つで、機器がネットワークの内側と外側の通信を中継する際のルールを定めています。このSOCKSに従ってネットワーク内外の通信を中継するサーバをSOCKSサーバといい、これがネットワークの境界に設置されることで通信の中継を行います。  

個人的な認識として、SOCKSサーバの役割はHTTPプロキシサーバに似ていると思います。ですが、SOCKSサーバはHTTPプロキシサーバと違い、UDPやTCP(SOCKS5のみ)の通信を中継しています。HTTPプロキシサーバがアプリケーション層のプロトコルであるHTTP通信を中継することを考えると、より低レイヤーであるトランスポート層のプロトコル(UDPやTCPのこと)の通信を中継するSOCKSサーバのほうが幅広い通信を扱うことができます。  

今回のダイナミックポートフォワーディングの場合、`-D`オプションを指定することで、SSH自体がSOCKSサーバの役割を果たすようになります。クライアントPCの中にSOCKSサーバが存在するかたちになるため、使用するときはコマンドで指定した自身のポートにアクセスし、リモートネットワークまで通信を中継してもらいます。

### 補足
ダイナミックポートフォワーディングを利用するためには、**利用するアプリケーションがSOCKSに対応している必要がある**ので注意が必要です。また、ブラウザからアクセスする場合は、事前にブラウザ側でSOCKSを利用する設定が必要になります。 
  
試したところ、FireFoxでは下記の設定からSOCKSの設定ができましたのでご参考まで
`設定 ＞ 一般 ＞ ネットワーク設定 ＞ インターネット接続に使用するプロキシーの設定 ＞ 手動でプロキシーを設定する`

IPアドレスの部分は`localhost`、ポートの部分は`コマンドで指定したポート`を設定します。

## おわりに
以上、SSHダイナミックポートフォワーディングについてまとめてみました。
私自身、ダイナミックポートフォワーディングはつい最近まで知りませんでした。とても便利な仕組みなので、今後活用する機会があれば積極的に使っていきたいと思います。

## 参考サイト
- [sshポートフォワーディングについて図示してみる](https://qiita.com/fkshom/items/844a1be031ae3eb4bcea#%E3%83%80%E3%82%A4%E3%83%8A%E3%83%9F%E3%83%83%E3%82%AF%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%89)
- [SSHを使ってSOCKS経由でWebにアクセスする方法](https://qiita.com/testnin2/items/64c570859b297dfac8b1)
- [ダイナミックポートフォワーディング（SOCKSプロキシ）の方法](https://blog.icttoracon.net/2020/02/21/%E3%83%80%E3%82%A4%E3%83%8A%E3%83%9F%E3%83%83%E3%82%AF%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%EF%BC%88socks%E3%83%97%E3%83%AD%E3%82%AD/)
- [SOCKSとは - 意味をわかりやすく - IT用語辞典 e-Words](https://e-words.jp/w/SOCKS.html)