[SOCKS Proxy] 踏み台を経由しないと接続できないWebアプリにブラウザで直接（つながっているかのように）アクセスできるようにする

やり方だけ知りたい方は[こちら](#SOCKS-Proxyの構成方法)へ

## SOCKS Proxyとは
### SOCKS Proxyで出来ること
SOCKS Proxyとは "Socket Secure Proxy" の略で、トラフィック（TCPだろうがUDPだろうが）をプロキシ経由で転送する技術です。

SSHでトンネルを張って、そのトンネルの先の端末から通信させるようにすることでプロキシとして使ってしまおうというわけです。

![SOCKS_Proxyのがいよ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835736/a08cf3e1-fd2f-4718-b268-01dd66316fb5.png)


### どんなときに使えるか
通常隔離環境にあるWebアプリにアクセスするには踏み台にRDPやX転送などでの接続が必要です。

![通常の踏み台経由のアクセス](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835736/cf982d00-97fb-46d9-9789-8bc96952359a.png)

踏み台で色々作業をするのであればまだしも、ただ隔離環境のWebアプリを開くためだけにWindowsやGUI付きのLinuxを構築するのはめんどくさいです。

そんなときに活躍するのがSOCKS Proxyです。

SOCKS Proxyでは踏み台に特別な要件は必要ありません。この2条件さえ満たせば大丈夫です。
* SSHで接続が出来ること
* 踏み台から直接Webアプリに接続出来ること（ルーティングやファイアウォールに問題がないこと）

:::note warn
踏み台側のSSH受信ポートを22ではなく、443とかにするとセキュリティが甘いFWであれば、外部へのSSHが封じられている環境でも案外抜けれたりします。
セキュリティ管理者の方はセキュリティホールとならないようしっかり対策しておきましょう。
:::

SOCKS Proxyを経由することで手元の端末から隔離環境のWebアプリにアクセス出来るようになります。

![SOCKS Proxyを利用したアクセスイメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835736/b85cde56-2f71-44e9-9420-cb587f4ced48.png)

### 内部的な動き
SOCKS Proxyを構成するにはSSHトンネル形成時に `-D` オプションを利用します。

`-D` オプションを利用することで手元の端末は `localhost:<指定したポート番号>` でSOCKS通信を待ち受けるようになります。

ブラウザ側でプロキシ設定をしてあげれば準備完了です。

あとはブラウザでURLを指定するとその通信は全てSSHトンネルを経由して踏み台に転送され、踏み台をプロキシとして対象URLにアクセスしに行きます。

![内部的な動き](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835736/62d7ec71-c275-48a3-aba4-2bf72728acc8.png)

## SOCKS Proxyの構成方法
今回はGoogle Cloud上にCompute Engineをデプロイし、そこからVPCピアリングの先のGCVEのvCenterにアクセスしてみたいと思います。

本筋と関係ないのでVPCピアリングの構成方法、GCVEやGCEのデプロイは割愛します。

### 構成
#### 構成図

![構成図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835736/deb74596-4717-4f60-9105-d4f1805f2e73.png)

踏み台には外部IPアドレスを持たせており、外からSSH出来るようにファイアウォールを構成しています。

また、踏み台とvCenter間はHTTPS通信出来るよう、VPC Peeringを構成してルーティング上問題ないこと、当該経路にファイアウォールが無いことは確認済みです。

#### 環境情報
| コンポーネント | 詳細 |
|:-:|:-|
| 手元の端末  |  Mac OS Sequoia |
| 利用ブラウザ  |  Google Chrome Version 134.0.6998.89 (Official Build) (arm64) |
| 踏み台GCE  |  Debian GNU/Linux 12 (bookworm) |

### 鍵の生成と登録 ※鍵認証の場合のみ
#### 鍵の生成
ざっと調べた感じGCEでユーザー/パスワード認証でのSSHログインは出来無さそうなので、鍵認証でログインできるようにします。

まずは手元の端末で鍵のペアを作ります。既に鍵のペアを持っているのであればそれを利用しても問題有りません。

```bash
hogehoge@localhost ~ % ssh-keygen -t rsa -f ~/.ssh/gcp -b 2048
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/hogehoge/.ssh/gcp
Your public key has been saved in /Users/hogehoge/.ssh/gcp.pub
The key fingerprint is:
SHA256:BFL6M83zVINpajXeYCgp6dxpmyu9qWStuuJN3SvZBM0 hogehoge@localhost
The key's randomart image is:
+---[RSA 2048]----+
|    ..o          |
|     + o . o     |
|    + = o O o    |
|   o = E * = .   |
|    o O S o .    |
|    .o.B +       |
|   .ooB.  .      |
|. oo.+.+.        |
|.oo+oo=o         |
+----[SHA256]-----+
```

出来上がった鍵を確認します。
```bash
hogehoge@localhost ~ % cat ~/.ssh/gcp.pub
ssh-rsa AAAAB3Nxxxxxxxxxxxxxx<省略>xxxxxxxxxx hogehoge@localhost

hogehoge@localhost ~ % cat ~/.ssh/gcp
-----BEGIN OPENSSH PRIVATE KEY-----
xxxxxxxxxxxxx<省略>xxxxxxxxxxxxx
-----END OPENSSH PRIVATE KEY-----
```

#### 鍵をGoogle Cloudに登録
Compute Engine > 設定 > メタデータより、SSH認証鍵ページで公開鍵（上記の`~/.ssh/gcp.pub`）を登録します。

![GCE_keypair.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835736/24ad8818-98da-4e00-91d5-d707c7f618bd.png)

登録してしばらくするとGCEの `authorized_keys` に登録されるので確認しておきます。

```bash
# GCE上で確認
hogehoge@instance-20250312-123127:~$ sudo cat ~/.ssh/authorized_keys
# Added by Google
ssh-rsa AAAAB3Nxxxxxxxxxxxxxx<省略>xxxxxxxxxx hogehoge@localhost
```

ついでにsshdの状態も確認しておきます。
```bash
hogehoge@instance-20250312-123127:~$ sudo systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-03-12 12:32:20 UTC; 20h ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 1465 (sshd)
      Tasks: 1 (limit: 1136)
     Memory: 12.1M
        CPU: 1min 24.793s
     CGroup: /system.slice/ssh.service
             └─1465 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

hogehoge@instance-20250312-123127:~$ sudo cat /etc/ssh/sshd_config
# 結果は省略
```

### SSH Loginを試す
手元の端末からSSHでのログインが出来るか確認しましょう。
```bash
# 手元の端末から鍵経由でのSSHを確認
hogehoge@localhost ~ % ssh -i ~/.ssh/gcp hogehoge@<GCEのGlobal IP>
```
繰り返しますが、SSH出来るのであればユーザー/パスワード認証でも全く問題有りません。

### SOCKS Proxyを張る
手元の端末でターミナルを2つ開きます。

1つ目のターミナルでSOCK Proxyを張ります。
```bash
# 1つ目のターミナル（SOCKS Proxyの構成）
ssh -D 1337 -C -N -i ~/.ssh/gcp hogehoge@<GCEのGlobal IP>
```
各オプションの説明は下記の通りです。ここらへんは自由にご調整ください。
| オプション | 内容 |
|:-:|:-|
| -D  | 指定したポート番号（ローカル）でリモートへの転送を待ち受ける  |
| -C  | 通信データの圧縮  |
| -N  | SSH先でコマンドを実行しない<br>※トンネルを張りたいだけなのでコマンド実行は不要 |
| -i  | 鍵ファイルの指定  |
| -f  | バックグラウンドで起動<br>※バックグラウンドで起動したことを忘れがちなので入れていない |

2つ目のターミナルではChromeを開きます。

Chromeを開き、プロキシ設定を手動で入れても良いのですがCLIの方が簡単です。
```bash
# 2つ目のターミナル（SOCKS Proxy経由設定の入ったChromeの起動
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --incognito --proxy-server="socks5://localhost:1337"
```

通常使うChromeと閲覧履歴を分けたいので `--incognito` オプションをつけていますが、必須ではありません。

以上です。快適なSOCKS Proxyライフを！