【はじめに】
今回の記事のきっかけは、AWS環境でセキュリティ調査を行っていた際のことです。 AWS Security Hubの検知項目を確認すると、SSH(22番)やRDP(3389番)のポートが開放されていることに対し、CRITICALやHIGHの警告が出ていました。
もちろん、接続元IPアドレスを制限するなどは行っていましたが、「そもそもポートを常時開放せずに接続する方法はないか?」と考えたのが始まりでした。
調べてみたところ、Session ManagerによるAWSコンソールからの直接接続やAWS Client VPNなど複数の手段が見つかりましたが、今回は「外部委託先やベンダーの方に、最小限の工数と高いセキュリティでアクセス環境を提供する」というケースを想定し、SSM(Systems Manager)を利用したポートフォワーディングの手順をまとめてみることにしました。
【環境や使用したもの】
- ローカル環境
- MacBook Air M4(Apple Silicon)
- AWS CLI v2
- Session Managerプラグイン(インストール手順は本記事で紹介)
- SSHクライアント / SSHキー(SSH接続する場合)
- RDPクライアント(RDP接続する場合)
- AWS環境
使用するAWSアカウントがAWS Organizationsに所属していること
IAM Identity Centerが構築済みで、対象アカウントへのアクセスが設定されていること
ssm:StartSession権限を含む許可セット(ここでは検証目的でAdministratorAccessを使用)が割り当てられていること
※ 本記事では、手順の解説をスムーズに進めるための検証目的としてAdministratorAccessを使用しています。
※ 実際の運用時にはセキュリティリスクを最小限に抑えるため、最小限の権限で設定されたものを使用してください。
接続先のEC2インスタンス
- IAMロール(AmazonSSMManagedInstanceCoreアタッチ済み)
- SSM Agentインストール済み
- アウトバウンドでHTTPS(443)が通ること
【ポートフォワーディングとは?】
SSM Session Managerのポートフォワーディングは、EC2インスタンスの特定ポートをローカルマシンのポートに転送する機能です。
通信は、SSMのHTTPS(443)を使用するため、セキュリティグループのインバウンドでSSHやRDPのポートを開ける必要がありません。
また、接続元IPアドレスの管理も不要になります。
【IAM Identity CenterやOrganizationsの使用について】
私の環境(AWSアカウント)は、AWS Organizationsに所属しており、普段からIAM Identity Centerを通じてCDKのデプロイなどが行える環境です。 そのため、今回の手順もこれらを前提としていますが、たとえ個人開発のアカウントであっても、これらのサービスの導入をお勧めします。
その上で、詳しい説明は省きますが、なぜこれらをお勧めするのか簡単に触れておきます。
一言でいうと、「安全で楽をするための土台」です。
- AWS Organizations:複数のAWSアカウントを統合管理するためのサービス。
- IAM Identity Center:1つのユーザーIDで複数のアカウントにログインできるようにするサービス。
ポートフォワーディング自体は標準のIAMユーザーでも動作しますが、IAM Identity Centerを使う最大のメリットは「認証情報の管理」にあります。
標準のIAMユーザーだと、有効期限が切れるたびに「アクセスキーの再発行とコピペ」という面倒な作業が発生しますが、IAM Identity Centerならaws sso loginコマンドを入力しブラウザで承認するだけで、あとはAWS CLIが認証情報を自動管理してくれます。
なお、CLIからこの便利なログイン機能を使うには、Organizations環境で作成された「組織インスタンス」である必要があります。
どちらも利用料は基本的に無料(※ 2026年2月時点)ですので、初期セットアップの手間だけで運用が楽になります。
※ (2026年2月時点で)IAM Identity Center自体の利用料は原則無料ですが、利用構成によっては関連サービス費用が発生する場合があります。最新情報は公式ページをご確認ください。
【既にSSO環境がある場合の追加作業】
私の環境のように、既にOrganizationsに所属し、SSOで接続してCDKデプロイなどを行っている場合、追加で必要な作業は極僅かです。
許可セット(IAM Identity Centerで)
AWSアカウントにAdministratorAccessが付与されていればssm:StartSessionを含む全権限があるため追加不要
EC2のインスタンスプロファイル 既にAWSコンソールからSession Managerでシェル接続できていれば追加不要 ポートフォワーディングも同じssmmessagesチャネルを使う
アウトバウンド通信 セキュリティグループのアウトバウンドが0.0.0.0/0であれば追加不要
※ 動作確認としては0.0.0.0/0でもいいですが、実際の運用では必要な宛先(SSM関連エンドポイント等)に絞ることを推奨。
ローカルマシン Session Managerプラグインのインストールのみ必要
【Session Managerプラグインのインストール】
以下の手順は、Appleシリコンを使用しているMacへのインストール手順です。
Intel MacやWindowsへのインストールは、下記のURLを参照し、自身の環境にあったものをインストールしてください。
Session Managerプラグインをダウンロードする。
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac_arm64/session-manager-plugin.pkg" -o "session-manager-plugin.pkg"ダウンロードしたプラグインをインストールする。
sudo installer -pkg session-manager-plugin.pkg -target /シンボリックリンクを作成する。
sudo ln -s /usr/local/sessionmanagerplugin/bin/session-manager-plugin /usr/local/bin/session-manager-pluginインストールができたか確認をする。
session-manager-plugin --version
バージョンが表示されれば、問題なくインストールができていると思われます。
【EC2側の設定(サーバーを新規構築する場合)】
必要な設定は、次の通りです。
IAMロール
信頼ポリシーでec2.amazonaws.comを指定し、AmazonSSMManagedInstanceCoreポリシーをアタッチ。
IAMロールの作成で、ウィザードから作成すると簡単に必要な設定が行えます。
- 「IAM」=>「ロール」=>「ロールを作成」を開く。
- 「信頼されたエンティティタイプ」から「AWSのサービス」を選択。
- 「ユースケース」の「サービスまたはユースケース」から「EC2」を選択し、「ユースケース」から「EC2 Role for AWS Systems Manager」を選択。
- 後はデフォルトの設定のまま進め、ロールを作成する。
上記手順で作製したロールをEC2作成時にセットしてください。
SSM Agent
Amazon Linux 2/2023、Windows Serverなどはプリインストール済み。
セキュリティグループ
SSHやRDPのインバウンドポートは不要。
アウトバウンドはHTTPS(443)が通ること。
【接続方法】
ここまで設定などの前準備が長かったですが、ここからは接続手順になります。
EC2(Linuxサーバー、Windowsサーバー)への接続手順を説明します。
ここまでの手順でも説明しましたが、前提条件として「IAM Identity Centerが構築済みで、対象アカウントへのアクセスが設定されていること」です。
シェル接続手順(SSHキー不要、Linux / Windows共通)
ファイル転送が不要で、シェル操作だけを行いたい場合は、これだけで十分です。
Linuxでは、bash / sh、WindowsではPowerShellが開きます。
ターミナルで以下のコマンドを入力する。
# SSOでのログイン認証 aws sso login --profile (SSO接続プロファイル名:my-profile) # セッションの接続 aws ssm start-session --profile my-profile --target (インスタンスID:i-xxxxxxxxxxxx)
SSH接続(Linuxインスタンス)
シェル接続だけでなく、ファイルのアップロード、ダウンロードを行いたい場合は、こちらの手順です。
ターミナルで以下のコマンドを入力する。
# SSOでのログイン認証 aws sso login --profile (SSO接続プロファイル名:my-profile) # セッションの接続 aws ssm start-session \ --profile (SSO接続プロファイル名:my-profile) \ --target (インスタンスID:i-xxxxxxxxxxxx) \ --document-name AWS-StartPortForwardingSession \ --parameters '{"localPortNumber":["50022"],"portNumber":["22"]}'異なるターミナルを開き、以下のコマンドで接続する。
# sshで接続する ssh -p 50022 ec2-user@localhost -i ~/.ssh/(秘密鍵:my-key.pem) # scpでファイルをアップロードする scp -i ~/.ssh/(秘密鍵:my-key.pem) -P 50022 \ file.txt ec2-user@localhost:/home/ec2-user/
上記手順「1」を実行し、ターミナルを開いたままにしておけば、手順「2」の応用として、以下の設定をアプリに行うことでアプリからの接続も可能です。
・ホスト名:localhost
・ポート番号:50022
・プロトコル:SFTP
・ユーザー:ec2-user
・鍵:(秘密鍵:my-key.pem)
RDP接続(Windowsインスタンス)
ファイルアップロード、ダウンロードは、RDPクライアント経由でコピペを行うことで可能です。
ターミナルで以下のコマンドを入力する。
# SSOでのログイン認証 aws sso login --profile (SSO接続プロファイル名:my-profile) # セッションの接続 aws ssm start-session \ --profile (SSO接続プロファイル名:my-profile) \ --target (インスタンスID:i-xxxxxxxxxxxx) \ --document-name AWS-StartPortForwardingSession \ --parameters '{"localPortNumber":["53389"],"portNumber":["3389"]}'RDPクライアントを使用し、以下の設定内容で接続を行います。
・ホスト名:localhost ・ポート番号:53389 ・ユーザー:(RDP接続が許可されたWindowsユーザー) ・パスワード:(RDP接続が許可されたWindowsユーザーのパスワード)Windowsのリモートデスクトップ接続だと、接続先は「localhost:53389」となります。
【外部委託先のアクセスを特定EC2に制限する】
IAM Identity Centerで外部委託先のアカウントを作っただけだと、権限次第で対象外のEC2にも接続できてしまいます。
それは、最初に定義した「外部委託先やベンダーの方に、最小限の工数と高いセキュリティでアクセス環境を提供する」を満たしていない状態になります。
そこで、専用の許可セットで接続先を制限します。
方法1:インスタンスIDで制限
以下の設定で指定されたインスタンスIDへの接続のみに制限することが出来ます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ssm:StartSession"],
"Resource": [
"arn:aws:ec2:ap-northeast-1:(アカウントID:xxxxxxxxxxxx):instance/(インスタンスID:i-xxxxxxxxxxxx)",
"arn:aws:ssm:ap-northeast-1:*:document/SSM-SessionManagerRunShell",
"arn:aws:ssm:ap-northeast-1:*:document/AWS-StartPortForwardingSession"
]
},
{
"Effect": "Allow",
"Action": ["ssm:TerminateSession", "ssm:ResumeSession"],
"Resource": ["arn:aws:ssm:*:*:session/${aws:userid}-*"]
}
]
}
上記設定で確実に制限できますが、インスタンスが増減するたびにポリシーの更新が必要となり運用の手間がかかります。
そこでお勧めは、次の方法です。
方法2:タグで制限
対象EC2にタグを付け、そのタグを持つインスタンスだけに接続を許可します。
ここでは、「Project:ConnectTest」というタグをEC2に付けたものとします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ssm:StartSession"],
"Resource": [
"arn:aws:ec2:ap-northeast-1:(アカウントID:xxxxxxxxxxxx):instance/*"
],
"Condition": {
"StringLike": {
"ssm:resourceTag/Project": ["ConnectTest"]
}
}
},
{
"Effect": "Allow",
"Action": ["ssm:StartSession"],
"Resource": [
"arn:aws:ssm:ap-northeast-1:*:document/SSM-SessionManagerRunShell",
"arn:aws:ssm:ap-northeast-1:*:document/AWS-StartPortForwardingSession"
]
},
{
"Effect": "Allow",
"Action": ["ssm:TerminateSession", "ssm:ResumeSession"],
"Resource": ["arn:aws:ssm:*:*:session/${aws:userid}-*"]
}
]
}
インスタンスの増減時にポリシー変更が不要となり、タグを付けるだけで管理できます。
また、複数タグでの絞り込みも可能です。
【まとめ】
今回は、SSMのポートフォワーディング機能を使い、セキュリティグループでインバウンドのポートを解放せずにEC2へ接続する手順をまとめてみました。
実際に構築・使用してみて感じたメリットは以下の3点です。
- SSHやRDPのポートを閉じられるため、攻撃対象を最小化できる。
- IAM Identity Centerで許可セットを一度作れば、あとはEC2のタグを付け替えるだけで権限をコントロールできる。
- セキュリティグループがシンプルに保たれるため、可読性が上がる。
外部委託先やベンダーの方へのアカウント発行もスムーズに行えるため、詳細な接続手順書を用意すれば、不慣れな方でも迷わず、かつ安全に作業を開始できる環境が提供できます。
もし、Security Hubの警告やポート開放、IP制限の運用に追われているなら、まずは検証環境から試してみるのはいかがでしょうか。
商標について
※ AWS、Amazon Web Services、およびAmazon Linux は、Amazon.com, Inc.またはその関連会社の商標です。 ※ MacBook Air、macOS は、Apple Inc.の商標です。 ※ Windows は、Microsoft Corporationの商標です。
引用・出典について
本記事で紹介しているインストール手順およびコマンドは、一部以下のAWS公式ドキュメントに基づいています。