― 「誰の通信を許可する?」をコードで考える ―
今回から、少し難しくなる。
ここまでは、
- VPC → ネットワークを作る
- Subnet → ネットワークを区切る
- Route Table → 通信の行き先を決める
- ALB → 負荷分散する
- Listener → 通信を振り分ける
- Target Group → 転送先を管理する
- EC2 → 実際に仕事をするサーバー
というように、
「このAWSサービスは何をするのか?」
を中心に勉強してきた。
でも、Security Groupは少し違う。
Security Groupは、
「誰の通信を許可するのか?」
を決めるルールだからだ。
🔥 今の構成をもう一度確認
現在の構成はこうなっている。
Internet
│
▼
Internet Gateway
│
▼
ALB
│
▼
Listener
│
▼
Target Group
│
▼
EC2
ここで考えてみよう。
もしインターネットからEC2へ直接アクセスできてしまったら?
Internet
│
├────────→ ALB → EC2
│
└────────→ EC2
これってどうだろう?
当然、あまり良くない。
本来は、
Internet
↓
ALB
↓
EC2
という経路にしたい。
そこで登場するのが、
Security Group
🔐 Security Groupとは?
Security Groupは、ざっくり言えば
「この通信は通していい。この通信はダメ」
というルールを設定するもの。
イメージとしては、建物の入口にいる警備員。
👮
Internet ─→ Security Group ─→ EC2
警備員が、
«「誰ですか?」»
と確認して、
«「ALBです」»
なら、
«「どうぞ」»
となる。
でも、
«「インターネットから直接来ました」»
なら、
«「帰ってください」»
となる。
もちろん実際のSecurity Groupが人間みたいに確認しているわけではないけど、考え方としてはかなり近い。
TerraformでSecurity Groupを作る
まずはALB用のSecurity Group。
resource "aws_security_group" "alb" {
}
これは、
ALBに適用するSecurity Groupを作る
という意味。
① name
name = "alb-sg"
Security Groupの名前。
今回は、
alb-sg
という名前を付ける。
② vpc_id
vpc_id = aws_vpc.main.id
ここで質問。
なぜSecurity Groupにも、
vpc_id
が必要なんだろう?
ポイントは、
Security GroupはVPCに所属する
ということ。
イメージすると、
VPC
│
├── ALB
│ └── ALB Security Group
│
└── EC2
└── EC2 Security Group
という関係。
だからTerraformでは、
«「このSecurity Groupは、このVPCに所属させてね」»
と指定する。
③ ingress
ここはかなり重要。
ingress {
}
"ingress" は、
入ってくる通信
を定義する。
例えば、
from_port = 80
to_port = 80
protocol = "tcp"
なら、
TCPの80番ポートへの通信
を許可する設定。
④ cidr_blocks
さらに、
cidr_blocks = ["0.0.0.0/0"]
とする。
これ、以前にも出てきた。
"0.0.0.0/0" は、
すべてのIPv4アドレス
を意味する。
つまり今回、
0.0.0.0/0
↓
世界中
↓
TCP 80番
↓
ALB
という通信を許可している。
ALBはインターネットからアクセスを受ける必要があるので、
Internet
↓
ALB : 80
という通信を許可する。
⑤ egress
今度はこちら。
egress {
}
"egress" は、
外へ出ていく通信
を定義する。
今回の設定は、
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
となっている。
ここで注意。
"protocol = "-1"" は、
すべてのプロトコル
を意味する。
つまり、
- TCP
- UDP
- ICMP
などを含めて許可する設定。
そのため、
from_port = 0
to_port = 0
だから「ポート0しか通らない」という意味ではない。
"protocol = "-1"" の場合、ポート指定は実質的に無視される。
つまり、
すべての送信先への通信を許可する
という設定になる。
完成形
ここまでをまとめると、
resource "aws_security_group" "alb" {
name = "alb-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
これで、
「インターネットからALBの80番ポートへの通信を許可するSecurity Group」
が作れる。
🔥 今日の問題
ここからが本番。
Q1
なぜSecurity Groupにも、
vpc_id
が必要なの?
Q2
ingress
と
egress
の違いは?
Q3【今日一番重要】
ALBのSecurity Groupでは、
cidr_blocks = ["0.0.0.0/0"]
として、
世界中から80番ポートへの通信を許可している。
では、EC2にも、
cidr_blocks = ["0.0.0.0/0"]
を書いていいだろうか?
理由も考えてみよう。
ヒントは、
Internet
│
▼
ALB SG
「世界中から80番OK」
│
▼
EC2 SG
「???」
│
▼
EC2
🎯 今日の考え方
今回からは、
「このサービスは何をする?」
だけではなく、
「誰と誰を通信させる?」
という視点も重要になる。
例えば最終的には、
Internet
│
▼
ALB SG
「世界中から80番OK」
│
▼
EC2 SG
「ALBからだけOK」
│
▼
RDS SG
「EC2からだけOK」
という構成を目指す。
これは、
必要な通信だけを許可する
という考え方。
AWSで非常に重要な、
最小権限の原則
につながってくる。
📝 今回の回答
今回の回答はこちら。
コードの説明
«"resource "aws_security_group" "alb""
セキュリティグループを作ります»
«"name = "alb-sg""
alb-sgという名前»
«"vpc_id = aws_vpc.main.id"
メインVPC»
«"ingress"
入ってくる»
«"from_port = 80"
ポート80から»
«"to_port = 80"
ポート80へ»
«"protocol = "tcp""
TCPプロトコルの通信»
«"cidr_blocks = ["0.0.0.0/0"]"
すべて受け付けます»
«"egress"
出るときは»
«"protocol = "-1""
-1プロトコル»
«"cidr_blocks = ["0.0.0.0/0"]"
すべての通信が通る»
🔎 今回のレビュー
今回は、正直ちょっと難しかったと思う。
でも、躓いたところがかなり分かりやすい回だった。
そして、その躓き方自体が悪いわけじゃない。
Security Groupは今までのAWSサービスと違って、
「サービスの役割」ではなく「通信ルール」
を考える必要があるからだ。
では、一つずつ確認していこう。
コードレビュー
"resource "aws_security_group" "alb""
«セキュリティグループを作ります»
その通り。
100点!💯
"name = "alb-sg""
«alb-sgという名前»
これもOK。
100点!
"vpc_id = aws_vpc.main.id"
«メインVPC»
これも正しい。
ただし、ここは後のQ1にもつながる重要ポイント。
"vpc_id" は、
「どのVPCに所属するSecurity Groupなのか」
を指定している。
"ingress"
«入ってくる»
完璧。
100点!💯
"from_port = 80"
«ポート80から»
"to_port = 80"
«ポート80へ»
方向としてはOK。
ただ、より正確には、
許可するポート範囲の開始と終了
を指定している。
今回は、
80 ~ 80
なので、80番だけ。
"protocol = "tcp""
«TCPプロトコルの通信»
これもOK。
100点!
"cidr_blocks = ["0.0.0.0/0"]"
«すべて受け付けます»
これも今回の文脈ではOK。
正確には、
すべてのIPv4アドレスからの通信を許可する
という意味。
⚠️ egressで一つ修正
ここ。
«ポート0は無いので通信を通さない»
これは違う。
今回、
protocol = "-1"
となっている。
これは、
すべてのプロトコルを許可する
という意味。
そのため、
from_port = 0
to_port = 0
でも、
「0番ポートだけ」
という意味にはならない。
今回の設定全体としては、
ALB
↓
外部への送信
↓
基本的にすべて許可
という設定。
ここは少し引っかかりやすいところなので、今の段階では、
«"protocol = "-1"" → すべてのプロトコル»
だけはしっかり覚えておこう。
Q1レビュー
質問は、
«なぜSecurity Groupにもvpc_idが必要なの?»
だった。
回答は、
«VPCからのインバウンド通信を通すため»
だった。
ここは惜しい!
70点くらい。
Security Groupの"vpc_id"は、
通信を通すためではない。
「どのVPCに所属するSecurity Groupなのか」を指定するため。
例えば、
VPC-A
└── Security Group A
VPC-B
└── Security Group B
というように、Security GroupはVPCと関係づけられる。
だから、
vpc_id = aws_vpc.main.id
は、
«「このSecurity Groupは、このVPCに所属させてください」»
という指定。
ここは、
「通信の設定」と「所属先の設定」を分けて考える
とかなり分かりやすくなる。
Q2レビュー
«ingressはEC2に入ってくる通信で、egressは出る通信»
ほぼ100点!
今回はEC2に限定しなくてOK。
Security Groupは、
- ALB
- EC2
- RDS
などにも関連付けられる。
だから正確には、
«Ingress = Security Groupで受信する通信»
«Egress = Security Groupから送信する通信»
と考えればOK。
95点!
Q3レビュー🔥
ここはかなり良かった。
回答は、
«EC2に全ての通信を通しちゃいけないからcidr_blocks = ["0.0.0.0/0"]を書いたらダメ!»
だった。
100点!💯
ただし、もう一段深く考えてみよう。
今回の構成は、
Internet
↓
ALB
↓
EC2
だった。
じゃあ、EC2が世界中から直接アクセスできたら、
Internet
├────→ ALB ────→ EC2
│
└──────────────→ EC2
という2本の経路ができてしまう。
本来作りたいのは、
Internet
↓
ALB
↓
EC2
こっち。
だからEC2のSecurity Groupでは、
「インターネット全体」ではなく「ALBからの通信だけ」
を許可する。
🎯 最終問題の回答
最後に出した質問。
«EC2のSecurity Groupは世界中を許可するべき?
それともALBだけ許可するべき?»
回答は、
«ALBだけ。»
これでOK。
そして理由も、
«EC2はALBからの通信を通したいから。»
と説明できている。
さらに、
«どこからでもアクセスできたらセキュリティ的にも、EC2に負荷がかかった時の負荷分散も上手くできなくなる。»
というところまで考えられている。
ここはかなり良い。
特に、
Internet
↓
ALB
↓
EC2
という設計した通信経路を守るためにSecurity Groupを使う
という考え方ができている。
💡 ここで一つだけ補足
「EC2へ直接アクセスできると、負荷分散ができなくなる」というより、
ALBを経由しない通信が発生してしまう
と考えると、より正確。
ALBを経由しない通信では、
- ALBによる負荷分散
- ヘルスチェック
- ターゲットの状態に応じた振り分け
などの仕組みを通らない。
だから、
Internet
↓
ALB
↓
Target Group
↓
EC2
という設計にしたいなら、
EC2はALBからの通信だけを許可する
という考え方になる。
🌟 今回の成績
項目| 点数
コード理解| 90点
Q1| 70点
Q2| 95点
Q3| 100点
最終問題| 100点
総合| 🌟91点🌟
今回は、前回までより点数は少し下がった。
でも、これは悪いことじゃない。
むしろ今回のテーマは、
「分からないところを発見する」
という意味ではかなり重要な回だった。
🚀 今回の一番大事なこと
今回、
«「なんか、どっかで躓いてる気がする。これが正しいかわからなくなってる……」»
という感覚が出てきた。
これ、学習では結構大事。
分からないまま、
«「たぶんこういうこと!」»
で進んでしまうより、
«「あれ?この理解、本当に合ってる?」»
と立ち止まれる方が強い。
今回も実際、
vpc_id
を、
«通信を通すため»
と考えていた。
でも実際には、
«Security Groupの所属するVPCを指定するため»
だった。
こういう小さなズレを一つずつ修正していけばいい。
📚 これからの授業方針
ここで一つ、今後のTerraform講座の方針を決めておく。
コードを書く授業は、そのまま続ける。
むしろ、もっと書く。
ただし、
コードを覚える
↓
正解する
ではなく、
AWSの構成
↓
必要な設定を考える
↓
Terraformを書く
↓
なぜそのコードなのか説明する
↓
レビュー
↓
実務ではどう使うか確認
という流れにしていく。
例えば、
«「Security Groupを作って」»
だけではなく、
«「ALBにはインターネットからHTTPを許可する。
EC2にはALBからのHTTPだけ許可する。
Terraformならどう書く?」»
というところまで自力で考えられるようにしていく。
分からないことを、分かるようにする。
そのためにコードを書く。
これが今回からのTerraform講座。
☁️ 次回予告
次回は、今回作ったSecurity Groupを、
実際にEC2へ適用する。
さらに、
Internet
↓
ALB
↓
EC2
という通信を、
ALB SG
↓
EC2 SG
というSecurity Group同士の関係で作っていく。
ここで、
「CIDRで許可する」
だけではなく、
「Security Groupを指定して許可する」
というAWSらしい設計が出てくる。
今回の「ALBだけ許可する」という考え方が、次回から実際のTerraformコードになる。
ここからどんどん、
「AWSを知っている」→「AWSをコードで組める」
に変えていこう。🔥☁️🚀