はじめに
Bastionのブログには以下のような図があります。どういった通信が流れているかいまひとつしっくりこなかったので、実際の通信などをみて理解を深めようと思います。
構成図
VCNにプライベートサブネットを作成、インスタンスを作成します。
SGWの有無でどんな影響があるのか、Bastionがどこからどのような通信をしているのかを確かめます。
結論としては以下のような流れです。
- クライアントからOSN内にあるBastionのパブリックエンドポイントに、ホスト名でアクセスしているように見える
- Bastionのセッションを作成すると、プライベートサブネット内にプライベートIPが作成される
- そのプライベートIP経由で、プライベートインスタンスのSSHへ接続しているように見える
- Computeインスタンス内のBastion pluginが、OSN内のBastionサービス関連のパブリックIPへTCP/443で接続していた
- SGWとそこに対するルーティングがないと、pluginがセッション作成に必要な通信をできず、コンソール上で失敗するような挙動になった
検証
SGWとルーティングの有無でのBastionへの影響
まず、SGWなしの状態で確認しました。
- SGWなしでBastionサービスを作成できるか
- 作成できた
- SGWなしでBastion pluginをRunning状態にできるか
- pluginをONにしても、7分程度はRunningにならなかった
- 変わらないのでSGWを作成すると、Runningになったように見えた
- SGWなしでセッションを作成できるか
- 作成中の状態が10分程度続き、その後削除済みになった
pluginがRunningになるまでの時間差なのか、SGWを通ってOSN内のBastionサービスと通信できたためなのかは、今回の試験だけでは切り分けられていません。
OCIの公式ドキュメントでは、VCNにはService Gateway、Internet GatewayまたはNAT Gatewayと、ゲートウェイへのルートルールが必要と説明されています。
セッション作成後にSGWを削除する
コンソール画面でセッションを作成した後にSGWを削除して、既存セッションのSSHを確認しました。
- セッション作成後にSGWを削除しても、既存セッションではSSHできた
- SGWを削除した状態で新しいセッションを作成すると、作成できなかった
このことから、SGWやルートは少なくとも新規セッションの作成・初期化時に必要だと考えています。
BastionのSSHから通信の経路を見てみる
クライアント -> Bastion -> プライベートインスタンス
今回見たのは管理対象SSHセッションです。
Bastionの画面でSSHコマンドを表示すると、Bastionのホスト名と、最後に接続するプライベートIPが入っていました。
ssh -i <PRIVATE_KEY> \
-o ProxyCommand="ssh -i <PRIVATE_KEY> -W %h:%p -p 22 <BASTION_SESSION_OCID>@host.bastion.<REGION>.oci.oraclecloud.com" \
-p 22 opc@<PRIVATE_TARGET_IP>
-
ProxyCommand内側のSSHがBastionのホスト名へ接続する -
-W %h:%pで、外側のSSHのTCPストリームを中継する - 外側のSSHは、最終的にプライベートIPのComputeへ接続する
Bastionのホスト名をDNSで引くと、OSN内にあるパブリックIPが返ってきました。
プライベートインスタンス内でTCP/22を見る
Bastionのセッションを作成すると、同じプライベートサブネット内にプライベートIPが作成されていました。
Compute側でTCP/22を見ると、次のように、そのプライベートIPから接続が来ていることが分かりました。
sudo ss -tnp | grep ':22'
<COMPUTE_PRIVATE_IP>:22 <REVERSE_CONNECTION_IP>:<EPHEMERAL_PORT> ESTAB
今回だと、次のように見えました。
10.10.0.10:22 10.10.0.174:17989
10.10.0.174 が、サブネットのIP管理画面に表示された ReverseConnectionIp になります。
プライベートインスタンス内の通信
どのような通信をしているかを見てみるために、Computeインスタンス内でDNSとTCP/443を観察しました。
sudo tcpdump -i any -s 0 -vvv '(port 53 or port 443)'
DNSでは、次のような名前解決が見えました。
bastion-session.<REGION>.oci.oraclecloud.com
-> cell-1.splat-api.<REGION>.oci.oraclecloud.com
-> <OCI_SERVICE_IP_1>
-> <OCI_SERVICE_IP_2>
CNAMEのIPを見てみると、フェニックスリージョンのOSN内にあるパブリックIPでした。
そのパブリックIPを対象にtcpdumpを実行しました。
sudo tcpdump -i any -nn -tttt -s 0 -vvv \
'tcp and port 443 and host <OCI_SERVICE_IP>'
Computeから、そのIPの443番へSYN、SYN/ACK、その後のTLS通信が見えました。
利用者からBastionへSSHしている通信とは別に、Compute内のBastions pluginがOSN内のBastionサービス関連エンドポイントと通信しているように見えます。
Bastionのログについて
Compute上のBastions pluginのログは、次の場所にありました。
/var/log/oracle-cloud-agent/plugins/bastions/bastions.log
SGWがない場合のログ
代表的なエラーは次の通りです。
failed to renew security token
failed to get security token
dial tcp <OCI_SERVICE_IP>:443: i/o timeout
このときtcpdumpでは、SYNの再送だけが続いてSYN/ACKが返りませんでした。
SGWがある場合のログ
SGWを作成して通信できるようにすると、次のようなログが確認できました。
Get sessions details took: time (ms)=28ms
Received OpcRequestId from data plane
Validating the SSHD setup
Synchronize sessions
authorizedKeysFile already contains SSH key for session
Bastion Agent workflow complete
プライベートIPについて
Bastionサービスは2つのプライベートIPを使用するように見えました。サブネットのIP管理タブには、次のような表示がありました。

ReverseConnectionIp
<REVERSE_CONNECTION_IP>
<BASTION_RESOURCE_OCID>
<BASTION_PRIVATE_IP_2>
ReverseConnectionIp は、ComputeのTCP/22で接続元として見えたため、BastionサービスからSSHしてくるためのIPではないかと考えています。
もう一つのプライベートIPについて、対象IPをtcpdumpで確認しました。
sudo tcpdump -i any host <BASTION_PRIVATE_IP_2>
特にパケットキャプチャでは通信していませんでした。何か別の通信で使われているのかもしれませんが、今回の観測だけでは分かりませんでした。
おわりに
Bastionのネットワーク通信から、構成の位置関係などを確認しました。
クライアントからBastion、Bastionからプライベートインスタンス、Compute内のBastions pluginからOSN側のBastionサービスという、複数の通信を分けて考える必要がありそうです。
また、Bastionを運用する際には、OSNへアクセスするためのSGW、NAT Gateway、Internet Gatewayのいずれかと、対応するルート設定が必要だと考えています。

