AWS SSM Port Forwarding をプライベートサブネット設計に組み込む方法|IAMポリシー構成

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > AWS(Amazon Linux) > AWS SSM Port Forwarding をプライベートサブネット設計に組み込む方法|IAMポリシー構成
「プライベートサブネットのRDSに手元のDBクライアントで接続したい。でも踏み台サーバーにSSHするのは面倒だし、セキュリティグループに22番ポートを開けるのも抵抗がある」

AWS SSM(Systems Manager)のポートフォワーディング機能を使えば、SSH接続もセキュリティグループの22番開放も不要で、プライベートサブネット内のリソースへローカルポート経由でアクセスできます。しかし「コマンドは知っているがIAMポリシーの最小権限設定がわからない」「VPCエンドポイントが足りなくて接続できない」という声をよく聞きます。

この記事では、aws ssm start-session --document-name AWS-StartPortForwardingSession をプライベートサブネット設計に組み込む手順と、最小権限を守るIAMポリシーの構成パターンを解説します。Amazon Linux 2023 / RHEL 9.4で動作確認済みです。

この記事のポイント

・aws ssm start-session でプライベートサブネットのRDS/Redisにローカル接続できる
・VPCエンドポイントは ssm・ssmmessages・ec2messages の3本が必要
・IAMポリシーはドキュメント名とインスタンスIDをResourceで限定して最小権限にする
・セキュリティグループの22番・3306番・5432番の受信ルールは不要になる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜSSMポートフォワーディングなのか

プライベートサブネットのEC2にSSHで入るには、パブリックサブネットに踏み台を立てるのが従来の手法です。しかし踏み台には「EC2コスト・管理負荷・22番ポートの外部公開」という三重のコストがかかります。

SSMポートフォワーディングは、EC2インスタンスにインストールされたSSM Agentがマネジメントコンソール側から通信を引っ張る仕組みです。インスタンスへの受信ポートは一切開ける必要がありません。通信経路はSSMのVPCエンドポイント経由でAWS内部に閉じるため、パブリックIPもインターネットゲートウェイも不要になります。

VPCとプライベートサブネット設計の基礎からおさらいしたい方は、AWS Amazon Linuxの実践セミナーでVPCアーキテクチャの「型」を体系的に学ぶことができます。

事前準備:VPCエンドポイントとIAMポリシー

1. 必要なVPCエンドポイント3本を確認する

インターネットゲートウェイを持たないプライベートサブネットでSSMを動かすには、以下の3本のインターフェース型VPCエンドポイントが必須です。

・com.amazonaws.ap-northeast-1.ssm:セッション制御チャネル
・com.amazonaws.ap-northeast-1.ssmmessages:セッションデータ転送チャネル
・com.amazonaws.ap-northeast-1.ec2messages:Run Command/Patch Manager共用

作成済みかどうかは次のコマンドで確認できます。

# VPCエンドポイントの一覧を確認する $ aws ec2 describe-vpc-endpoints --filters "Name=vpc-id,Values=vpc-0a1b2c3d4e5f67890" --query 'VpcEndpoints[*].{Service:ServiceName,State:State}' --output table ------------------------------------------------------------------------------------------- | DescribeVpcEndpoints | +-----------+-----------------------------------------------------------------------------+ | State | Service | +-----------+-----------------------------------------------------------------------------+ | available| com.amazonaws.ap-northeast-1.ec2messages | | available| com.amazonaws.ap-northeast-1.ssm | | available| com.amazonaws.ap-northeast-1.ssmmessages | +-----------+-----------------------------------------------------------------------------+

3本すべてが available であることを確認します。1本でも欠けるとSSMセッションが確立できません。また、各エンドポイントのセキュリティグループで、EC2インスタンスのセキュリティグループからの443番(HTTPS)インバウンドを許可してください。

2. IAMポリシーをポートフォワーディング専用に絞る

ポートフォワーディング専用の最小権限ポリシーは次のとおりです。AmazonSSMManagedInstanceCore を丸ごと付けるのではなく、実行できるドキュメントとターゲットインスタンスをResourceで限定します。

{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPortForwarding", "Effect": "Allow", "Action": "ssm:StartSession", "Resource": [ "arn:aws:ec2:ap-northeast-1:123456789012:instance/i-0123456789abcdef0", "arn:aws:ssm:ap-northeast-1::document/AWS-StartPortForwardingSession", "arn:aws:ssm:ap-northeast-1::document/AWS-StartPortForwardingSessionToRemoteHost" ] }, { "Sid": "AllowSessionManagement", "Effect": "Allow", "Action": [ "ssm:TerminateSession", "ssm:ResumeSession", "ssm:DescribeSessions", "ssm:GetConnectionStatus" ], "Resource": "arn:aws:ssm:*:*:session/-*" } ] }

ポイントは2つです。

・ssm:StartSession の Resource にインスタンスARNとドキュメントARNを並記する。これをしないと「AccessDeniedException」が出る
・ssm:TerminateSession の Resource に -* を付けると、他ユーザーのセッションを誤って終了させるリスクを防げる

なお、EC2インスタンス側のIAMロールには AmazonSSMManagedInstanceCore が必要です(SSM AgentがSSMサービスへ登録するため)。

aws ssm start-sessionでポートフォワーディングを実行する

1. 基本コマンドとパラメータ

ポートフォワーディングのコマンド書式は次のとおりです。

# ローカルの15432番をEC2経由でRDS(5432番)へ転送する $ aws ssm start-session --target i-0123456789abcdef0 --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["5432"],"localPortNumber":["15432"]}' Starting session with SessionId: tomohiro-0a1b2c3d4e5f67890 Port 15432 opened for sessionId tomohiro-0a1b2c3d4e5f67890. Waiting for connections...

「Waiting for connections...」と表示された状態がセッション確立済みです。この端末を開いたまま、別の端末から psql -h 127.0.0.1 -p 15432 -U postgres mydb のように接続します。

--target にはSSM Agentが動いているEC2インスタンスIDを指定します。RDS自体はSSM管理対象外なので、プライベートサブネット内の中継EC2を経由させる設計が基本です。RDSへの直接ポートフォワーディングには AWS-StartPortForwardingSessionToRemoteHost ドキュメントを使います(後述)。

2. RDSへの直接ポートフォワーディング(RemoteHost指定)

EC2をポートフォワーディングの中継点にしつつ、接続先ホスト名をRDSエンドポイントへ向ける方法が AWS-StartPortForwardingSessionToRemoteHost です。EC2にデータベースクライアントを入れる必要がなくなります。

# EC2(i-0123456789abcdef0)経由でRDSエンドポイントの5432番に転送する $ aws ssm start-session --target i-0123456789abcdef0 --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{ "host":["mydb.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com"], "portNumber":["5432"], "localPortNumber":["15432"] }' Starting session with SessionId: tomohiro-0b2c3d4e5f678901 Port 15432 opened for sessionId tomohiro-0b2c3d4e5f678901. Waiting for connections...

この接続が成立している状態で、セッションが開いているかどうかはローカルのポート確認で検証できます。ss -tlnp や lsof -i :15432 で15432番がLISTEN状態になっていれば正常です(Linux ポート確認の全コマンド)。

3. セッションを安全に終了する

# 実行中のセッションIDを確認する $ aws ssm describe-sessions --state Active --query 'Sessions[*].{ID:SessionId,Target:Target,Start:StartDate}' --output table --------------------------------------------------------------------------- | DescribeSessions | +--------------------------------------+-----------------+----------------+ | ID | Start | Target | +--------------------------------------+-----------------+----------------+ | tomohiro-0b2c3d4e5f678901 | 2026-10-11T.. | i-01234... | +--------------------------------------+-----------------+----------------+ # セッションを終了する $ aws ssm terminate-session --session-id tomohiro-0b2c3d4e5f678901 { "SessionId": "tomohiro-0b2c3d4e5f678901" }

端末で Ctrl+C を押してもセッションは終了しますが、terminate-session でサーバー側から明示的に切断するほうがCloudTrailログに終了記録が残り、監査対応がしやすくなります。

プライベートサブネット設計への組み込み方

SSMポートフォワーディングをプライベートサブネット設計に組み込む際のセキュリティグループ設計を整理します。

EC2インスタンスのセキュリティグループ(アウトバウンドのみ):
・443(HTTPS)→ VPCエンドポイントのセキュリティグループ:必須
・22(SSH):不要(インバウンドは一切開けない)

RDS/ElastiCacheのセキュリティグループ:
・5432/3306/6379 → EC2のセキュリティグループ:EC2からのインバウンドのみ許可
・インターネット側からの受信ルールは一切不要

この設計により、外部からの直接攻撃面は実質ゼロになります。接続経路はSSMのTLS通信に一本化され、CloudTrailでユーザーごとのアクセス履歴を追跡できます。

マルチAZ設計でActive/StandbyのEC2が複数ある場合、IAMポリシーの ssm:StartSession のResourceをインスタンスARNではなくタグ条件に変えることで、自動フェイルオーバー後も同じポリシーで接続できます。

# タグ条件でポートフォワーディングを許可する例(マルチAZ対応) { "Effect": "Allow", "Action": "ssm:StartSession", "Resource": "arn:aws:ec2:ap-northeast-1:123456789012:instance/*", "Condition": { "StringEquals": { "ssm:resourceTag/Env": "prod", "ssm:resourceTag/Role": "ssm-bastion" } } }

ssm:resourceTag 条件キーにより、タグ Env=prod かつ Role=ssm-bastion が付いたインスタンスにのみポートフォワーディングを限定できます。

トラブルシュート:接続できない時の確認手順

「An error occurred (TargetNotConnected)」が出る
EC2インスタンス上のSSM Agentが停止しているか、VPCエンドポイントが不足しています。インスタンス内で systemctl status amazon-ssm-agent を確認し、停止していれば systemctl start amazon-ssm-agent で起動します。VPCエンドポイントの3本セットが揃っているかも再確認してください。

「AccessDeniedException」が出る
IAMポリシーのResource指定が不完全です。ssm:StartSession のResourceにインスタンスARNとドキュメントARNの両方を記載しているか確認してください。「arn:aws:ssm:region::document/AWS-StartPortForwardingSession」の形式でリージョンとアカウントIDの間にコロンが2つ(::)あることに注意です。

ローカルポートには繋がるがDB接続がタイムアウトする
RDSのセキュリティグループが中継EC2からのインバウンドを許可していない可能性があります。RDSのセキュリティグループで「インバウンド→EC2のセキュリティグループID→ポート5432」を確認してください。

本記事のまとめ

やりたいこと コマンド・設定
EC2経由でRDS(5432番)にローカル転送 aws ssm start-session --target i-xxx --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["5432"],"localPortNumber":["15432"]}'
RDSエンドポイントへ直接ポートフォワード aws ssm start-session --target i-xxx --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host":["rds-endpoint"],"portNumber":["5432"],"localPortNumber":["15432"]}'
IAM最小権限:ドキュメント限定 Resource に インスタンスARN と AWS-StartPortForwardingSession ドキュメントARNを並記
マルチAZ対応:タグ条件で絞る Condition に ssm:resourceTag/Env + ssm:resourceTag/Role を設定
VPCエンドポイント確認 aws ec2 describe-vpc-endpoints で ssm / ssmmessages / ec2messages の3本を確認
セッション強制終了 aws ssm terminate-session --session-id セッションID
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、AWS Amazon Linuxセミナーの詳細はこちら>>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。