どーも!shihopowerです!今回はセキュリティグループについてお話します。SAP 対策でセキュリティグループに関する問題が出題されたのですが、セキュリティグループに関する記憶が抜け落ちていることに気づきました。おさらいを兼ねて本質的な理解ができるように、AWS 公式ドキュメントをもとに深掘りしてみました。
本記事の内容は AWS 公式ドキュメントをもとにしています。
忙しい人向け要約
セキュリティグループ(SG)とは何か
VPC 内のリソースに関連付ける仮想ファイアウォール。許可ルールのみ書ける。
最重要:ステートフル
リクエストを許可すれば、レスポンスは自動で返ってくる。レスポンス用のルールを別途書く必要はない。
SG の適用単位は「ENI」
インスタンスそのものではなく、アタッチされている ENI(仮想 NIC)に紐付く。IP アドレスやセキュリティグループといったネットワークの属性はすべて ENI 側が持つ。
EC2 → Aurora の最小権限設定はこの 2 つだけ
| 対象 SG | 方向 | 内容 |
|---|---|---|
| EC2 の SG | アウトバウンド | 宛先=DB の SG、port 3306 |
| DB の SG | インバウンド | ソース=EC2 の SG、port 3306 |
迷ったときの考え方
「誰が接続を開始するか」を起点に考える。開始する側にアウトバウンド、受け入れる側にインバウンドを書く。レスポンスはステートフルが自動で面倒を見てくれる。
目次
- きっかけの問題:EC2 → Aurora への最小権限アクセス
- セキュリティグループの本質
- 「全インスタンスが同じ SG に関連付けられている」とはどういう状態か
- セキュリティグループはどのレベルで適用されるのか
- ENI(Elastic Network Interface)とは何か
- IP アドレスはインスタンスに付くのではなく ENI に付く
- 複数の SG を関連付けられるのか?SG がない状態はあるのか?
- まとめ:問題の正解を改めて整理する
1. きっかけの問題:EC2 → Aurora への最小権限アクセス
「あれ、どっちにどのルールを書くんだっけ?」
SAP の問題を解いていてそう思った瞬間がありました。問われていたのはこういうシチュエーションです。
- VPC 内に EC2 インスタンスが複数台あり、全台が同じセキュリティグループに入っている
- 同じ VPC 内に Aurora DB クラスターがあり、別のセキュリティグループに入っている
- EC2 上のアプリケーションが Aurora に接続する必要がある
- このとき、最小権限でアクセスを許可するには、どのセキュリティグループにどんなルールを追加すればいいか?
選択肢には「EC2 側にインバウンド」「EC2 側にアウトバウンド」「DB 側にインバウンド」「DB 側にアウトバウンド」など複数の組み合わせが並んでいました。
正解は次の 2 つです。
- EC2 のセキュリティグループにアウトバウンドルールを追加する(宛先: DB の SG、ポート: Aurora のデフォルトポート)
- DB のセキュリティグループにインバウンドルールを追加する(ソース: EC2 の SG、ポート: Aurora のデフォルトポート)
「なんで EC2 側はアウトバウンドで、DB 側はインバウンドなの?」「EC2 側にインバウンドは要らないの?」という疑問が湧いてきました。この疑問を解消するために、セキュリティグループの本質から順番に掘り下げてみます。
2. セキュリティグループの本質
仮想ファイアウォールとしての役割
AWS 公式ドキュメントによると、セキュリティグループは関連付けられたリソースへの通信を制御するバーチャルファイアウォールです。EC2 インスタンスに関連付ければ、そのインスタンスへのインバウンド・アウトバウンド両方のトラフィックを制御します。
VPC を作成すると、デフォルトのセキュリティグループが自動的に付いてきます。追加でセキュリティグループを作成することもでき、それぞれにインバウンド・アウトバウンドのルールを設定できます。
ステートフルとはどういう意味か
セキュリティグループの最も重要な性質がステートフルであることです。
公式ドキュメントにはこう書かれています。
Security groups are stateful. For example, if you send a request from an instance, the response traffic for that request is allowed to reach the instance regardless of the inbound security group rules.
(意訳)セキュリティグループはステートフルです。たとえば、インスタンスからリクエストを送信すると、そのレスポンストラフィックはインバウンドのセキュリティグループルールに関係なくインスタンスへの到達が許可されます。
つまり、一度確立した接続のレスポンスは、明示的なルールがなくても自動的に返ってくるということです。
これを冒頭の問題に当てはめると、
- EC2 → Aurora への接続(ポート 3306)を許可すれば、Aurora → EC2 へのレスポンスは自動で通る
- わざわざ EC2 側にインバウンドルールを書く必要はない
「EC2 側にインバウンドルールが要らない理由」はここにあります。
EC2 ──[アウトバウンド port 3306]──▶ Aurora
EC2 ◀──[レスポンス:自動で許可]────── Aurora
ルールは「許可のみ」——拒否は書けない
もう一つ重要なことがあります。セキュリティグループには許可ルールしか書けません。拒否ルールを書く手段はありません。
また、新規作成したセキュリティグループにはインバウンドルールがゼロの状態から始まります。つまりデフォルトで全インバウンドが遮断されています。アウトバウンドは初期状態で全許可のルールが入っています。
3. 「全インスタンスが同じ SG に関連付けられている」とはどういう状態か
問題文に「EC2 インスタンスはすべて同じセキュリティグループに関連付けられている」とありました。これはどういう状態でしょうか。
セキュリティグループはルールの入れ物
セキュリティグループの正体はルールをまとめた入れ物です。インスタンスそのものにルールが書かれているわけではなく、「このセキュリティグループに入っているリソースに適用されるルール」を SG が持っています。
インスタンスを起動するときに「どの SG に入れるか」を指定します。これが「関連付け」です。
4 台の EC2 インスタンスがあっても、全台が同じ SG-EC2 に入っていれば、SG-EC2 に書いたアウトバウンドルール 1 つで全台に自動で適用されます。
SG-EC2
├── EC2 インスタンス A
├── EC2 インスタンス B
├── EC2 インスタンス C
└── EC2 インスタンス D
(アウトバウンドルール: 宛先=SG-DB, port 3306)
↓ 全台に一括適用
IP アドレスではなく SG を参照することが「最小権限」の実現
DB 側のインバウンドルールのソースに SG-EC2 を指定すると、「この SG に入っているリソースからの通信を許可する」という意味になります。
公式ドキュメントによると、セキュリティグループをソースまたは宛先として指定すると、そのセキュリティグループに関連付けられたすべてのインスタンスのプライベート IP アドレスからの通信が対象になります。
IP アドレスで指定してしまうと、インスタンスが増えたり IP が変わったりするたびにルールを書き直す必要があります。SG を指定しておけば、SG-EC2 に新しいインスタンスを追加するだけで自動的に許可対象になります。これが最小権限を保ちながら柔軟に運用できる設計です。
4. セキュリティグループはどのレベルで適用されるのか
ここで一つ疑問が出てきます。「セキュリティグループはインスタンス単位で適用されるのか? サブネット単位ではないのか?」
答えはインスタンスレベルです。AWS 公式ドキュメントの比較表にはっきりこう書かれています。
| 項目 | セキュリティグループ | ネットワーク ACL |
|---|---|---|
| 適用レベル | インスタンスレベル | サブネットレベル |
| ルール種別 | 許可ルールのみ | 許可・拒否の両方 |
| ステートフル | はい(レスポンスは自動許可) | いいえ(明示的に許可が必要) |
| 適用範囲 | 関連付けられたリソースのみ | サブネット内の全インスタンス |
同じサブネット内に 10 台のインスタンスがあっても、セキュリティグループを変えれば台ごとに異なるトラフィック制御ができます。これがサブネット全体に一律で適用されるネットワーク ACL との最大の違いです。
さらに正確に言うと、セキュリティグループはインスタンスそのものではなくENI(Elastic Network Interface)に紐付きます。
5. ENI(Elastic Network Interface)とは何か
「ENI って何?」となりますよね。
仮想 NIC ——リソースをネットワークに繋ぐ接続口
公式ドキュメントによると、ENI はVPC 内の論理的なネットワークコンポーネントで、仮想ネットワークカード(NIC)を表します。
物理サーバーに LAN ケーブルの差し込み口(NIC)がなければネットワークに繋げられないように、EC2 も ENI がなければ VPC 内で通信できません。ENI はそのリソースとネットワークをつなぐ「接続口」です。
ENI が持つ属性
ENI には次のような属性が含まれています。
- プライベート IPv4 アドレス(サブネットの CIDR から付与)
- パブリック IPv4 アドレス
- Elastic IP アドレス
- セキュリティグループ
- MAC アドレス
- 送信元/宛先チェックフラグ
重要なのは、これらの属性は ENI 自体に紐付いているという点です。インスタンスを変えても、ENI をそのまま持っていけば属性はすべて引き継がれます。
ENI が適用されるサービス
ENI を持つすべてのリソースにセキュリティグループを適用できます。主なサービスは以下のとおりです。
- EC2 インスタンス
- Amazon RDS / Aurora
- ALB / ELB(ロードバランサー)
- AWS Fargate(ECS タスク)
- AWS Lambda(VPC 接続時)
公式ドキュメントには「ENI を持つすべての AWS リソースに関連付けられるファイアウォールとして機能する」と記載されています。
6. IP アドレスはインスタンスに付くのではなく ENI に付く
ここが個人的に一番「なるほど!」となった部分です。
「ネットワークインターフェイスには IP アドレスなどの属性が含まれている」ということは……インスタンスやその他のリソースは、IP アドレスが直接付与されるのではなく、IP アドレスの情報が含まれている ENI がアタッチされることでその IP アドレスで通信できる、ということではないか?
この理解は正しかったです。
IP アドレスは ENI に帰属する
公式ドキュメントにはこう書かれています。
The attributes of a network interface follow it as it's attached or detached from an instance and reattached to another instance. When you move a network interface from one instance to another, network traffic is redirected from the original instance to the new instance.
(意訳)ネットワークインターフェイスの属性は、インスタンスにアタッチされたり、デタッチされたり、別のインスタンスに再アタッチされたりするときも引き継がれます。
つまり、インスタンス本体は「計算を行うコンピュートリソース」に過ぎず、IP アドレスやセキュリティグループといった「ネットワークとしての素性」はすべて ENI 側が持ちます。
公式ドキュメントにはさらに、「EC2 インスタンスを起動すると、IP アドレスはプライマリネットワークインターフェイスに割り当てられる」とも書かれています。あくまでインスタンスではなく、ENI に割り当てられるわけです。
これがフェイルオーバーをシンプルにする
この仕組みの実用的なメリットがよく分かるのがフェイルオーバーです。
【障害発生前】
インスタンス A ← ENI(IP: 10.0.1.10, SG: sg-xxx)
【障害発生後】
インスタンス A(停止)
インスタンス B(スタンバイ)← ENI を付け替え(IP: 10.0.1.10, SG: sg-xxx のまま)
公式ドキュメントには「ネットワークインターフェイスはプライベート IP アドレス、Elastic IP アドレス、MAC アドレスを維持するため、アタッチした瞬間から新しいインスタンスにトラフィックが流れ始める。ルートテーブルや DNS サーバーを変更する必要はない」と記載されています。
IP が ENI に帰属するからこそ、インスタンスが変わっても IP・SG はそのまま。DNS やルートの変更も不要というわけです。
7. 複数の SG を関連付けられるのか?SG がない状態はあるのか?
複数の SG を関連付けられる
はい、できます。公式ドキュメントには「1 つのリソースに複数のセキュリティグループを割り当てることができる」と明記されています。
複数関連付けた場合のルールの扱いも公式ドキュメントに書かれています。
When you associate multiple security groups with a resource, the rules from each security group are aggregated to form a single set of rules that are used to determine whether to allow access.
(意訳)複数のセキュリティグループをリソースに関連付けると、各 SG のルールが集約されて 1 つのルールセットが形成され、アクセスを許可するかどうかの判定に使われます。
たとえば SG-A が「HTTP を許可」、SG-B が「SSH を許可」していれば、両方を関連付けたリソースは HTTP も SSH も受け付けます。ルールは**より多くを許可する方向に合算(OR)**されます。
SG がない状態は存在しない
「起動時に SG を指定しなかったら何もない状態になるの?」という疑問も出てきます。
そうはなりません。公式ドキュメントによると、デフォルトの VPC および作成する VPC には、デフォルトセキュリティグループが付属しています。インスタンス起動時にセキュリティグループを指定しなかった場合は、その VPC のデフォルトセキュリティグループが自動的に関連付けられます。
デフォルト SG のルール
デフォルト SG のルールは次のとおりです。
インバウンド(デフォルト)
| ソース | プロトコル | ポート |
|---|---|---|
| このSG自身のID | すべて | すべて |
アウトバウンド(デフォルト)
| 宛先 | プロトコル | ポート |
|---|---|---|
| 0.0.0.0/0 | すべて | すべて |
インバウンドは「同じデフォルト SG に入っているリソース同士の通信」だけ許可されます。インターネットゲートウェイや NAT ゲートウェイからのインバウンドは許可されません。アウトバウンドはすべて許可です。
公式ドキュメントには「デフォルト SG は削除できない」とも書かれています。ただしルールは変更可能です。
8. まとめ:問題の正解を改めて整理する
一通り深掘りした上で、冒頭の問題に戻りましょう。
「EC2 から Aurora DB への最小権限アクセスを実現するためのセキュリティグループ設定」
| 追加するルール | 対象 SG | 方向 | 内容 | 理由 |
|---|---|---|---|---|
| ✅ EC2 のアウトバウンドルール | EC2 の SG | アウトバウンド | 宛先=DB の SG、port 3306 | EC2 が接続を開始する側 |
| ✅ DB のインバウンドルール | DB の SG | インバウンド | ソース=EC2 の SG、port 3306 | DB が接続を受け入れる側 |
不要なルールとその理由:
- ❌ EC2 のインバウンドルール:EC2 は DB からリクエストを受ける側ではない。DB への接続を開始するのは EC2 側。
- ❌ DB のアウトバウンドルール(デフォルトポート):DB からアクティブに接続を開始することはない。
- ❌ DB のアウトバウンドルール(エフェメラルポート):セキュリティグループはステートフルなので、レスポンスは自動で許可される。明示的なアウトバウンドルールは不要。
深掘りして得られた理解
今回の深掘りで得られたことをまとめると、
- ステートフルだからレスポンスルールを書かなくていい
- SG はルールの入れ物であり、インスタンス単位ではなく ENI 単位で適用される
- IP ではなく SG を参照することで最小権限・柔軟な運用が実現できる
- IP アドレスは ENI に帰属するので、ENI 付け替えで IP ごと引き継げる
- SG のない状態は存在しない——指定がなければデフォルト SG が適用される
セキュリティグループの設問で迷ったときは「誰が接続を開始する側か」を起点に考えると整理しやすいです。開始する側にアウトバウンド、受け入れる側にインバウンドを書く。レスポンスはステートフルが面倒を見てくれる。
この理解があれば、セキュリティグループ絡みの問題は自信を持って解けるはずです💪