セキュリティグループ設定で盛大にハマって時間を食ったので、備忘録としてまとめます。
- 目的:TerraformでEC2を立ててSSM(Session Manager)で接続し、22番を開けない / 鍵管理をなくす
- 症状:マネジメントコンソールから SSM接続できない
- 結論:Security Group のアウトバウンド(Egress)が全拒否になっていて、SSMが必要とする アウトバウンド 443 が塞がっていた
参考ドキュメント
- Terraform AWS Provider:
aws_security_group
何をしたかったか
Terraformでこんな構成を作りました。
- EC2(アプリ)を起動
- インバウンドは必要最低限(例:アプリの3000だけ)
- SSH(22)は開けず、代わりに SSMで接続
SSMで接続できれば、
- 22を開けない(踏み台不要 / ポートスキャンの面倒が減る)
- キーペア運用(鍵の配布・失効・漏洩対応)を減らせる
…という期待でした。
起きたこと(症状)
IAMロール(AmazonSSMManagedInstanceCore)は付けているのに、コンソールからSession Managerで接続しようとすると失敗。
原因調査のために結局SSHで接続し、
-
amazon-ssm-agentの存在と起動は確認できた - でも EC2内から
curl https://example.comが返ってこない
ここで「外向き通信が死んでる=ネットワーク(特にEgress)が怪しい」と判断しました。
SSM(Session Manager)の通信の仕組み
SSMは「クライアント→EC2」に直接つなぎにいく仕組みではありません。
SSHとの違い
- SSH:クライアント →(インバウンド22)→ EC2
- SSM:EC2上のSSM AgentがAWS側のSystems Managerへアウトバウンドで通信し続けることで成立
つまり、SSMは “外から入ってくる”のではなく“中から取りに行く(張りにいく)”モデルです。
SSMは「ポーリング+双方向チャンネル」
SSM Agent は概ね以下の動きをします。
- 定期的にAWS側へポーリングを送る
- 「このインスタンスは生きてます」「どのバージョンです」など
- セッション開始時は、AWS側(Session Manager)と双方向の通信チャネルを張る
- 入力(あなたのキーボード)と出力(シェルの結果)をストリーミングするイメージ
このとき必要なのがアウトバウンドのHTTPS(tcp/443)です。
なぜ原因特定に時間がかかったか
普段AWSのSecurity Groupは「アウトバウンド全許可」になっていることが多く、Egressで詰まる発想になりにくいです。
しかし、今回のSGはアウトバウンドルールが空(= 全拒否)になっていました。
結果として、
-
curl https://example.comがタイムアウト / 接続できない -
dnf update/dnf installも失敗する - SSM AgentもAWSへ到達できず、結果としてSSM接続できない
結論(今回の原因)
そもそも公式のドキュメントの読み込みが甘かったです。
以下の部分を読み飛ばしていました。

簡単に訳すと、「AWSはデフォルトでアウトバウンドを全許可で作るけど、Terraformはこれを除外しますよ〜。必要なら自分で追加してね」ということらしいです。
Security Groupのアウトバウンド(Egress)が全拒否になっており、SSMに必要なアウトバウンド443が通っていなかった。
何を変更したか
Before(Egressを書いていなかった)
resource "aws_security_group" "allow_myip" {
name = "allow_myip"
description = "allow myip"
vpc_id = aws_vpc.main.id
tags = {
Name = "allow_myip"
}
}
resource "aws_vpc_security_group_ingress_rule" "allow_myip_3000" {
security_group_id = aws_security_group.allow_myip.id
cidr_ipv4 = local.myip_cidr
from_port = 3000
to_port = 3000
ip_protocol = "tcp"
}
After(アウトバウンド443を明示)
resource "aws_security_group" "allow_myip" {
name = "allow_myip"
description = "allow myip"
vpc_id = aws_vpc.main.id
# 追加:アウトバウンドHTTPS(443)を許可(SSM / パッケージ取得 / curl など)
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Name = "allow_myip"
}
}
resource "aws_vpc_security_group_ingress_rule" "allow_myip_3000" {
security_group_id = aws_security_group.allow_myip.id
cidr_ipv4 = local.myip_cidr
from_port = 3000
to_port = 3000
ip_protocol = "tcp"
}
学び
ドキュメントはしっかり読みましょう(自戒の意味も込めて)