OCI Bastion経由でプライベート・サブネット内のComputeインスタンスに接続

__初めに__
冒頭ですが、この記事の位置付けは、次のシリーズ記事の1つです。
シリーズ１：[OCI Bastion サービス](https://qiita.com/letian/items/10152a4fec813c1b7d98#bastion-%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9)
シリーズ２：[プライベート・サブネット内の OCI Compute に接続](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98#3-%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88%E3%82%B5%E3%83%96%E3%83%8D%E3%83%83%E3%83%88%E5%86%85%E3%81%AE-oci-compute-%E3%81%AB%E6%8E%A5%E7%B6%9A)

プライベート・サブネットに配置されているOCI Computeインスタンスに接続する方法はいくつかあります。インターネットを利用する場合、パブリックサブネット内の踏み台サーバを経由するのが一般的です。

OCI Bastion サービスを利用すれば、<strong>踏み台サーバを立てず</strong>、On-Pのクライアントから、プライベート・サブネット内の Compute インスタンスに接続できます。

メリット：
✅ 踏み台サーバを立てる必要がないため、コストを節約できる。
✅ SSHトンネルで通信するので、セキュアな接続を確保できる。
✅ OCI Bastion自体は無料で利用できる。
✅ 設定方法は比較的やりやすい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/3a2cfd5e-538c-e7b5-d90f-64c391eead60.png)
では、OCI Bastion を介してプライベートな <strong>Windows/Linux</strong> インスタンスに接続する方法を紹介したいと思います。

__目次__

- [1. 事前準備](#1-事前準備)
  - [1-1. 関連する OCI リソースの作成](#1-1-関連する-oci-リソースの作成)
  - [1-2. OpenSSH のインストール](#1-2-openssh-のインストール)
- [2. Bastionの作成](#2-bastionの作成)
- [3. セキュリティ・リストに入力ルールを追加](#3-セキュリティリストに入力ルールを追加)
- [4. Linux VMに接続する](#4-linux-vmに接続する)
  - [4-1. セッションの選択](#4-1-セッションの選択)
  - [4-2. 管理対象SSHセッションで接続](#4-2-管理対象sshセッションで接続)
  - [4-3. ポート転送セッションで接続](#4-2-管理対象sshセッションで接続)
- [5. Windows VMに接続する](#5-windows-vmに接続する)
  - [5-1. セッションの作成](#5-1-セッションの作成)
  - [5-2. SSHトンネルの作成](#5-2-sshトンネルの作成)
  - [5-3. RDPでログイン](#5-3-rdpでログイン)
- [付録](#付録)
  - [トラブル・シューティング](#トラブルシューティング)
  - [Bastionの制限](#bastionの制限)

# 1. 事前準備
## 1-1. 関連する OCI リソースの作成
|タイプ|項目|値|コメント|
|:--|:--|:--|:--|
|VCN|CIDR|10.0.0.0/16|
|プライベート・サブネット|CIDR|10.0.1.0/24|接続先サーバ|
|サービスGW (※1)||||
|ルート表 (※1)|ルール|ターゲット: サービスGW<br>宛先: `All <Region_Key> Services in Oracle Services Network`|ターゲットVMのサブネットに紐づける|
|セキュリティ・リスト|Egress<br>(※1)|0.0.0.0/0, 全てのプロトコル|同上|
|Compute インスタンス|OS|Oracle Linux <strong>9</strong>|プライベート IP: 10.0.1.8|
||OS|Windows サーバ <strong>2022</strong>|プライベート IP: 10.0.1.138|

※1、<strong>管理対象SSHセッション</strong>を指定する場合、作成必要。
## 1-2. OpenSSH のインストール
OCI Bastionサービスの本質は<strong>SSHトンネル</strong>です。クライアント側からSSHトンネルを経由して接続先サーバにアクセスするため、事前にSSHソフトのインストールが必要です。

この例ではOpenSSHを使用します。まだインストールされていない場合は、PowerShellを起動し、以下のコマンドでインストールしてください（管理者ユーザで実行）。

コマンド：`Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'`
```powershell
PS C:\windows\system32> Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'


Name  : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name  : OpenSSH.Server~~~~0.0.1.0
State : NotPresent



PS C:\windows\system32>
```

# 2. Bastionの作成
Identity & Security -> Bastion -> Create Bastion
Bastion名を入力し、ターゲットVCNとサブネットを選択してから、CIDRブロック許可リストを入力します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/a005b706-53d1-8280-c381-fabf7ccd0b2b.png", width="500">

__注意__
1. このテストでは、CIDRブロックの許可リストを「0.0.0.0/0」に設定しています。運用時には範囲を絞り込むことが推奨されます。例えば、接続元（クライアント）のIPアドレス範囲のみを許可するのが良いでしょう。
2. OCI Bastionを作成する際には、<strong>ターゲット</strong>のVCNとサブネットを指定する必要がありますが、<strong>Bastion自体</strong>に対し、<strong>配置場所を指定する必要はありません</strong>（誤解されることがよくあります）。

Bastionがアクティブの状態になると、「<font color=blue>プライベート・エンドポイントIP</font>」は次の画面から確認できます。このIPはターゲット・サブネット内で自動的に割り当てられます。次のステップで、このIPをセキュリティ・リストの入力ルールに追加します。「CIDRブロック許可リスト」を編集したい場合は、「<strong>編集</strong>」ボタンをクリックすれば大丈夫です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/20136580-5a36-e7c8-8533-d77390e52fb0.png)

# 3. セキュリティ・リストに入力ルールを追加
プライベート・サブネット内のインスタンスにアクセスするため、TCPポート(<font color=blue>3389, 22</font>)を入力ルールに追加するのは必要です。
設定方法は、以下のどちらでもよいです。
* プライベート・サブネットに紐づけられる<strong>セキュリティ・リスト</strong>に、ルールを追加
* Computeインスタンスに紐づけられる<strong>NSG</strong>に、ルールを追加

セキュリティ・リストを例にして設定します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/29ecd06c-f374-2a51-23d8-23e2e660d9fa.png", width="650">

"<strong>Source CIDR</strong>"は、Bastionの「プライベート・エンドポイントIP」です（Bastionの情報ページに表示されます）。

__追加後__
ポート 3389: Remote Desktop Protocol (Windows VM 接続用)
ポート 22: SSH (Linux VM 接続用)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/d5ca92cb-1c86-9227-3b53-df958ee5b10a.png">

# 4. Linux VMに接続する
Windows VMに接続する場合、このステップを飛ばして、[次のステップ](#5-windows-vmに接続する)を実施してください。

## 4-1. セッションの選択

セッション・タイプは、以下の２種類があります。
- 管理対象SSHセッション (Managed SSH session)
- ポート転送セッション (SSH port forwarding session)

__セッション・タイプの差異比較__
|タイプ|前提条件|対応OS|リソース・タイプ|備考|
|--|--|--|--|--|
|管理対象SSHセッション|1.Bastionプラグインは<strong>有効化</strong>(Enabled)されている、かつ<strong>稼働中</strong>(Running)になっている。<br>2.サービスGWが作成され、ルート表に追加済。|Linux|VM|セッション作成時、ターゲットVMに接続できる。|
|ポート転送セッション|BastionプラグインとサービスGWは不要|Linux/Windows|VM, Oracle Base DB, Autonomous DB, MySQL DB|SSHトンネル作成後、通常のSSH/RDPで接続|

※、Bastionラグインの状態は、インスタンスの詳細画面(<strong>Oracle Cloud Agentタブ</strong>)から確認できます。Oracle Linuxインスタンスを作成した直後、Bastionラグインの状態は"<strong>Disabled</strong>"となっています。管理対象SSHセッションを選択する場合、Bastionセッションを作成する前、次のBastionラグインを有効化にする必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/f5ba5600-ddca-f3bc-b7c9-77c92eaddeed.png)


## 4-2. 管理対象SSHセッションで接続
Bastion -> Sessions -> Create session
|項目|内容|
|--|--|
|セッション・タイプ|"<font color=blue>Managed SSH session</font>"を選択|
|ユーザー名|opc|
|コンピュート・インスタンス|対象コンパートメントの下から選択する|
|SSHキー|既存のキーファイルを利用するか、新しいキーペアを作成する。(秘密キーをクライアント側に保存してください。)|

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/411a444d-1d86-ba7c-5012-e72ca7a3f9d7.png", width="500">

セッションはアクティブの状態になりましたら、次のように、3ドットのメニューをクリックしてSSHコマンドをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/141ff0a3-8051-ba80-b49c-6b803648ae0c.png)

__SSHセッションの作成__
接続元のクライアントでコピーしたコマンドを実行してセッションを作成します。

__コマンド__
`ssh -i <privateKey> -o ProxyCommand="ssh -i <privateKey> -W %h:%p -p 22 <OCID_of_Bastionsession>@host.bastion.ap-tokyo-1.oci.oraclecloud.com" -p 22 opc@<Private_IP_of_Target_VM>`

* `<privateKey>`を秘密キーのパスとファイル名に置き換えます。

PowerShellでの接続例：
```powershell
PS C:\users\opc> ssh -i $home\.ssh\id_rsa -o ProxyCommand="ssh -i $home\.ssh\id_rsa -W %h:%p -p 22 ocid1.bastionsession.oc1.ap-tokyo-1.amaaaaaakv6tzsaagj47utdtn5vqisr5bvin7yz3f5livaqjzi2e2k3oos6a@host.bastion.ap-tokyo-1.oci.oraclecloud.com" -p 22 opc@10.0.1.15
The authenticity of host '10.0.1.15 (<no hostip for proxy command>)' can't be established.
ECDSA key fingerprint is SHA256:<fingerprint>.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.1.15' (ECDSA) to the list of known hosts.
[opc@linux9-private ~]$
```

## 4-3. ポート転送セッションで接続
Bastion -> Sessions -> Create session
|項目|内容|
|--|--|
|セッション・タイプ|"<font color=blue>SSH port forwarding session</font>"を選択|
|ターゲット・ホストに接続する方法|"IPアドレス"を選択 (デフォルト)|
|IPアドレス|接続先VMの「プライベートIP」|
|ポート|<font color=blue>22</font>|
|SSHキー|既存のキーファイルを利用するか、新しいキーペアを作成する。(秘密キーをクライアント側に保存してください。)|

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/107e528d-7446-b7d1-3d4c-82bfd2f5eac2.png", width="500">

セッションはアクティブの状態になりましたら、次のように、3ドットのメニューをクリックしてSSHコマンドをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/64df9acf-3ced-e216-3aba-974be0d5f2ac.png)

__SSHトンネルの作成__
接続元のクライアントでSSHコマンドを実行してトンネルを作成します。

__コマンド__：
```bash
ssh -i <privateKey> -N -L <localPort>:<Private_IP_of_VM>:22 -p 22 <OCID_of_Bastionsession>@host.bastion.ap-tokyo-1.oci.oraclecloud.com
```
* `<privateKey>`を秘密キーのパスとファイル名に置き換えます。
　Windowsの例（PowerShell）：`$home\.ssh\id_rsa`
* `<localPort>`を<font color=blue>22</font>に置き換えます。
* `<Private_IP_of_VM>`は自動に実のIPが埋められるので、変更する必要はありません。

```powershell
PS C:\Users\Wei> ssh -i $home\.ssh\id_rsa -N -L 22:10.0.1.8:22 -p 22 <OCID_of_Bastionsession>@host.bastion.ap-tokyo-1.oci.oraclecloud.com
The authenticity of host 'host.bastion.ap-tokyo-1.oci.oraclecloud.com (192.29.38.223)' can't be established.
RSA key fingerprint is SHA256:<fingerprint>.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'host.bastion.ap-tokyo-1.oci.oraclecloud.com,192.29.38.223' (RSA) to the list of known hosts.


```
SSHトンネルができたら、セッションが保留されますので、リターンキーが戻りません。強制終了をしたい時、"CTRL+C"を押してください。

__SSHでログイン__
もう一個PowerShell画面を起動して、次のコマンドでログインします。

__コマンド__：`ssh -i <private_key> localhost -l <username>`

例：`ssh -i $home\.ssh\id_rsa localhost -l opc`

```powershell
PS C:\Users\Wei> ssh -i $home\.ssh\id_rsa localhost -l opc
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:<fingerprint>.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
[opc@linux9 ~]$
```

# 5. Windows VMに接続する
Windows VMの場合、"Managed SSH session"は適用できないのでご注意ください。
## 5-1. セッションの作成
Bastion -> Sessions -> Create session
|項目|内容|
|--|--|
|セッション・タイプ|"<font color=blue>SSH port forwarding session</font>"を選択<br>|
|ターゲット・ホストに接続する方法|"IPアドレス"を選択 (デフォルト)|
|IPアドレス|接続先VMの「プライベートIP」|
|ポート|<font color=blue>3389</font>
|SSHキー|既存のキーファイルを利用するか、新しいキーペアを作成する。(秘密キーをクライアント側に保存してください。)|

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/17e135dd-b4fe-4735-fc12-39843484838a.png", width="500">
セッションはアクティブの状態になりましたら、次のように、<strong>3ドット</strong>のメニューをクリックしてSSHコマンドをコピーします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/851c397f-3a24-6444-436f-99a0e7ab3194.png">
デフォルトでは、セッションは<font color=blue>３時間</font>有効です。Bastionを作成する時に変更できます。

## 5-2. SSHトンネルの作成
接続元のクライアントでSSHコマンドを実行してトンネルを作成します。

__SSHトンネルを作成するコマンド__：
```bash
ssh -i <privateKey> -N -L <localPort>:<Private_IP_of_VM>:3389 -p 22 <OCID_of_Bastionsession>@host.bastion.ap-tokyo-1.oci.oraclecloud.com
```

* `<privateKey>`を秘密キーのパスとファイル名に置き換えます。
　Windowsの例（PowerShell）：`$home\.ssh\id_rsa`
* `<localPort>`を<font color=blue>13389</font>に置き換えます。(3389を区別するため)
* `<Private_IP_of_VM>`は自動に実のIPが埋められるので、変更する必要はありません。

<font color=blue>ヒント</font>:
* バック・グラウンドで実行させたい場合：
   Windows (PowerShell):  `Start-Job {  }`でコマンドを囲む
   Linux OSを使用する時、コマンドの最後に`&`を追加
   バック・グラウンドで実施する場合、出力メッセージを表示しませんので、ご注意ください。<strong>初回トンネル作成時</strong>、或いは<strong>トラブル・シューティング</strong>の時、<font color=blue>フォア・グラウンド・プロセス</font>として実施してください。


```powershell
PS C:\Users\Wei> ssh -i $home\.ssh\id_rsa -N -L 13389:10.0.1.138:3389 -p 22 <OCID_of_Bastionsession>@host.bastion.ap-tokyo-1.oci.oraclecloud.com

```
上記のようにフォア・グラウンドとして実施した場合、セッションが保留されますので、リターンキーが戻りません。強制終了をしたい時、"CTRL+C"を押してください。

## 5-3. RDPでログイン
クライアントでリモート・デスクトップを起動し、`localhost:13389`を入力してから接続ボタンをクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/d4002b68-9f7a-830d-e775-ec24fe144298.png", width="550">

次のように、ログイン画面が表示されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/cc426362-3395-bffd-0df6-e2ba5dd9cf4d.png", width="550">

# 付録
## トラブル・シューティング
接続が失敗した場合、以下のような原因は一般的です。ご参考ください。

- 秘密キーの中身或いは置き場所は不正。（例：`C:\Users\<Username>\.ssh\id_rsa`）
- Computeインスタンスは、まだ起動していない。
- プライベート・サブネットのセキュリティ・リストに、TCP <strong>22</strong>か<strong>3389</strong>を公開していない。
- Bastionのプライベート・エンドポイントIPが、Ingressルールに追加されていない。
対策：セキュリティ・リストまたはNSGを確認してください。
- <strong>サービス・ゲートウェイ</strong>がない、或いはルート表に追加されていない時、セッションを作成しようとしたら、次のエラーが発生した。(<strong>管理対象SSHセッション</strong>の場合のみ)
`Plugin Bastion not present for instance <OCID_of_instance>` 
- SSHトンネルは未作成か、作成が失敗した。
トンネル作成失敗、或いはタイムアウトの時、次のメッセージが表示される。
`Connection to host.bastion.ap-tokyo-1.oci.oraclecloud.com closed by remote host.`
- Bastionのセッション期限が切れた（デフォルトは３時間）。
セッション期限が切れた後、SSHトンネルを作成しようとしたら、次のエラーが発生した。
`<OCID_of_Bastionsession>@host.bastion.ap-tokyo-1.oci.oraclecloud.com: Permission denied (publickey)`
対策：セッションの再作成は必要。

## Bastionの制限

|項目|内容|
|--|--|
|最大Bastion数|テナンシ毎に<font color=blue>5つ</font>|
|最大セッション数|Bastionあたり<font color=blue>20</font>セッション|
|セッション存続時間|<font color=blue>30分~3時間</font>|
|データ転送制限|データ転送の制限はありません。<br>ただし、SSH接続あたりの接続速度は<font color=blue>16 Mbps</font>に制限されます。|

以上です。

----
__改訂歴__
2022年12月：初版作成
2023年05月：管理対象SSHセッションの接続例を追加
2023年05月：セッション・タイプの差異比較を追加

----
__関連記事__
[オラクル・クラウドの個人ブログ一覧](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98)
[プライベート・サブネット内のOCI Computeインスタンスに接続する方法のまとめ](https://qiita.com/liu-wei/items/e0376fd71433d243bce0)
[ネットワーク・ロード・バランサ (NLB) の経由でプライベート・サブネット内の OCI VMに接続する](https://qiita.com/liu-wei/items/d4144794ef1a8692580c)
[リモート・デスクトップ・ゲートウェイ経由で OCI Windows VM に接続する方法](https://qiita.com/liu-wei/items/15e2e74f5a8c304002a3)
[OCI Bastion経由でプライベート・サブネット内のOracle DBに接続する](https://qiita.com/liu-wei/items/36f2108992ce71d7bafc)
[OCI Bastion経由でプライベート・サブネット内のAutonomous DBに接続](https://qiita.com/liu-wei/items/36dc12c95d3bc72e16db)
[OCI Bastion経由でMySQL Cloud Serviceに接続](https://qiita.com/liu-wei/items/e86e01ac3d61999aa811)

__ドキュメント__
[要塞](https://docs.oracle.com/ja-jp/iaas/Content/Bastion/home.htm)