AWSで自宅PCに外部からSSH接続するための踏み台サーバーをCloudFormationで構築する

# AWSで自宅PCに外部からSSH接続するためのBastionサーバーをCloudFormationで構築する

自宅PCに固定IPがなくても、AWS上に踏み台（Bastion）サーバーを立てて**リバースSSHトンネル経由で外部からアクセス**できる構成をまとめました。
また、踏み台サーバーをCloudFormationで自動構築できるテンプレートを作成しました。

## やりたいこと

- 外部（ノートPC等）から自宅PCにSSH接続したい
- でも自宅PCは固定グローバルIPを持っていない
- そのため、AWS上に踏み台サーバーを立て、自宅PC→Bastionへの**リバースSSHトンネル**を常時接続する
- せつぞくもｔPCは踏み台を経由して、自宅PCにSSH接続する
- Route 53 で `bastion.example.com` のようなドメイン名でも接続できるようにしたい

---

## 構成図

``` mermaid
graph TD
  C[接続元PC（例：ノートPC）] -->|ssh bastion.example.com| B[Bastionサーバー（AWS）]
  A[自宅PC（ホームサーバー）] -->|リバーストンネル<br>ssh -R 2222:localhost:22 bation.example.com| B
  B -->|ssh localhost:2222| A
```

---

## 準備

### sshのキーペア作成

- 踏み台接続用
    - プライベートキーを接続元PC・ホームサーバーに設置すること
- 自宅PC接続用
    - 踏み台サーバー作成後、プライベートキーを踏み台サーバーに設置すること
        - ProxyJumpで一括接続するなら、接続用PCにもプライベートキーを設置しておくこと

### 踏み台用ドメイン取得

- 自分は、AWSでドメインを取得しました
    - 参考：[【2024年版】AWSで独自ドメインを取得してみた！](https://techblog.ap-com.co.jp/entry/2024/05/22/093000)

### 踏み台サーバー作成（CloudFormationスタック作成）

- [GitHubにCloudFormationテンプレートを掲載](https://github.com/OrangeJuice652/BationWithSSHTunnelAndRoute53)

### 自宅PC起動時、踏み台-自宅PC間にリバーストンネルを自動接続（Systemd）

- 自宅PCを起動時に、自動で踏み台-自宅PC間のリバーストンネルを接続させるようにすると便利なので、systemdサービスを有効化しておきます

#### 自宅PCで、`/etc/systemd/system/reverse-ssh.service `を作成

```
[Unit]
Description=Reverse SSH Tunnel to Bastion
After=network.target

[Service]
ExecStart=/usr/bin/ssh -NT -i ~/.ssh/{踏み台接続用プライベートキー} \
  -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes \
  -R 2222:localhost:22 tunneluser@bastion.example.com
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

#### `/usr/bin/ssh -NT -i ~/.ssh/{踏み台接続用プライベートキー} -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -R 2222:localhost:22 tunneluser@bastion.example.com`

| オプション                                             | 意味                                                                                                                   |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `-N`                                              | **「リモートコマンドを実行しない」**<br>つまりSSH接続はするが、シェル等は開かず、ポートフォワードなどの通信トンネルだけを張る用途に使います                                          |
| `-T`                                              | **TTY（仮想端末）を割り当てない**<br>バックグラウンドや systemd 経由での実行に適しています                                                              |
| `-o ServerAliveInterval=60`                       | **60秒ごとにkeep-aliveパケットを送信**<br>SSHセッションのタイムアウト防止に有効                                                                  |
| `-o ExitOnForwardFailure=yes`                     | **ポートフォワードに失敗したらプロセス終了**<br>リバーストンネルの失敗を検知しやすくするための安全対策                                                            |
| `-R 2222:localhost:22`                            | **リバースポートフォワードの指定**<br>Bastionサーバー側で `localhost:2222` にアクセスすると、<br>自宅PC（このコマンドを実行している側）の `localhost:22`（SSH）に転送される |                                                                                                                      |

#### サービスを有効化

``` 
sudo systemctl daemon-reload
sudo systemctl enable reverse-ssh
sudo systemctl start reverse-ssh
```

---

## 外部PCからの接続方法

接続元PCに`~/.ssh/config`を作成（ProxyJumpで）

```
Host bastion
  HostName bastion.example.com
  User tunneluser
  IdentityFile ~/.ssh/{踏み台接続用プライベートキー}

Host home-server
  HostName localhost
  Port 2222
  User username
  ProxyJump bastion
  IdentityFile ~/.ssh/{自宅PC接続用プライベートキー}

```

これで踏み台を通して自宅PCに接続が可能となる
```
ssh home-server
```

## まとめ
- 自宅PCがグローバルIPを持っていなくても外部からSSH接続できる 
- 踏み台はCloudFormationで一発構築可能
- Route 53でドメイン名アクセスもOK
- Systemdで常時リバース接続も可能

## 参考記事

[グローバルなIPを持たないPCへSSHでインターネット経由の接続する方法](https://zenn.dev/tkr923/articles/45830fc43e2111)