AWS RDS セキュアローカルターミナル接続
Body:
パブリックアクセス可能ではない RDS インスタンスに psql(または任意の Postgres クライアント)を接続するためのリファレンス — インターネットに公開することなく。
基本的な考え方: RDS は Postgres プロトコルのみを話し、SSH ではありません。したがって、トンネルは常に VPC 内の RDS に到達できる何かで終了します。その後、psql を localhost に指定すると、トンネルがそのパケットを RDS に送信します。
RDS エンドポイントに直接接続することはなく、localhost に接続します。
2 つのルート
| ルート | EC2 が必要? | コスト | 最適用途 |
| SSM ポートフォワーディング | 小さなインスタンス(アイドル時は停止可能) | 停止時は ~$0、24/7 稼働時は ~$3/月 | 時々手動でクエリを実行 |
| EC2 Instance Connect Endpoint(EIC) | なし | エンドポイント時間課金なし | 「インスタンス管理不要」セットアップ |
いずれかを選択。どちらも psql -h localhost で終了します。
前提条件(両ルート共通)
-
AWS CLI v2 がインストールおよび構成されている(
aws configureまたは SSO)。 -
AWS CLI 用の Session Manager プラグイン:
- macOS:
brew install --cask session-manager-plugin - またはお使いの OS に対応した AWS ドキュメントに従ってください。
- macOS:
-
IAM プリンシパルが SSM / EC2 Instance Connect アクションのアクセス許可を持っている。
-
RDS エンドポイント(例:
mydb.xxxx.us-east-1.rds.amazonaws.com)とポート5432を把握している。 -
RDS セキュリティグループが、VPC 内の何か(bastion のセキュリティグループまたは EIC エンドポイントのセキュリティグループ)からのインバウンド
5432を許可している。
ルート A — SSM ポートフォワーディング(アイドル時に停止できる bastion 経由)
1. 最小限のインスタンスを起動(1 回)
-
タイプ:
t4g.nano(最安価、Arm)。 -
RDS と同じ VPC 内のサブネットに配置(プライベートサブネットで問題なし)。
-
パブリック IP、SSH、インバウンドポート不要。
-
AmazonSSMManagedInstanceCoreマネージドポリシーを含む IAM インスタンスプロファイルをアタッチ。 -
最新の Amazon Linux 2023 AMI を使用(SSM エージェントはプリインストール)。 SSM に登録されていることを確認:
aws ssm describe-instance-information \
--query "InstanceInformationList[].InstanceId"
インスタンス ID が表示されるはずです。表示されない場合、IAM ロールまたはサブネット SSM エンドポイントへのルーティングが原因である可能性が高いです。
2. bastion が RDS に到達できるようにする
RDS セキュリティグループに、インバウンドルール Postgres / TCP 5432 を追加し、ソースを bastion のセキュリティグループ に設定します。
3. トンネルを開始
aws ssm start-session \
--target i-0abc123yourinstance \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["mydb.xxxx.us-east-1.rds.amazonaws.com"],"portNumber":["5432"],"localPortNumber":["5432"]}'
このターミナルを開いたままにしておきます — トンネルを保持します。
4. 接続
psql -h localhost -p 5432 -U myuser -d mydbname
5. 完了後、インスタンスを停止(これがコスト削減のコツです)
aws ec2 stop-instances --instance-ids i-0abc123yourinstance
停止されたインスタンスは、コンピュート費が**$0**です。月額数セント程度の小さな EBS ルートボリュームのみを支払います。次回使用時に再度開始:
aws ec2 start-instances --instance-ids i-0abc123yourinstance
ルート B — EC2 Instance Connect Endpoint(インスタンスなし)
プライベートサブネット内にエンドポイント ENI を作成して、そこを通してトンネルします。実行または停止するインスタンスはありません。
注:EIC Endpoint の RDS などの非 EC2 ホストへのフォワーディング正確なサポートは進化し続けています。本番環境で使用する前に、お使いのリージョンの AWS ドキュメントで現在の動作を確認してください。以下の形式は一般的なアプローチを反映しています。
1. エンドポイントを作成(1 回)
-
RDS と同じ VPC 内のサブネットに EC2 Instance Connect Endpoint を作成。
-
5432上の RDS へのアウトバウンドが許可されたセキュリティグループを付与。 -
RDS セキュリティグループで、EIC エンドポイントのセキュリティグループからのインバウンド
5432を許可。
2. トンネルを開く
aws ec2-instance-connect open-tunnel \
--instance-connect-endpoint-id eice-0abc123 \
--private-ip-address <rds-private-ip-or-host-target> \
--remote-port 5432 \
--local-port 5432
開いたままにしておきます;トンネルを保持します。(正確なフラグは現在の CLI バージョンに依存します — aws ec2-instance-connect open-tunnel help を確認してください。)
3. 接続
psql -h localhost -p 5432 -U myuser -d mydbname
よくある落とし穴
ローカルポートがすでに使用中。 ローカルで Postgres を実行している場合、5432 は使用中です。別のローカルポートにフォワーディングして psql に指示:
# トンネルコマンドで localPortNumber / --local-port を 5433 に設定してから:
psql -h localhost -p 5433 -U myuser -d mydbname
SSL / 証明書エラー。 RDS はしばしば SSL を強制します。トンネルを通すと、クライアントはホストを localhost と見なし、厳密な証明書ホスト名検証に失敗する可能性があります。sslmode=require を使用してホスト名を検証せずに暗号化:
psql "host=localhost port=5432 dbname=mydbname user=myuser sslmode=require"
完全な検証の代わりに、RDS CA バンドルをダウンロードして sslmode=verify-full と sslrootcert= を使用してください — 本当に必要な場合のみの価値があります。
パスワード。 psql がプロンプトするパスワードは、AWS 認証情報とは別の Postgres ユーザーのパスワード。(DB が IAM 認証を使用する場合、代わりに aws rds generate-db-auth-token で短期トークンを生成します。)
トンネルドロップ。 フォワーディングセッションはタイムアウトまたはネットワーク変更でドロップする可能性があります。トンネルコマンドを再開するだけ。
クイックメンタルモデル
psql -> localhost:5432 -> [トンネル] -> RDS:5432
^
SSM bastion または EIC エンドポイント
(VPC 内のもの)
常に localhost と対話します。トンネルが唯一の変動部分です。