跳到正文Lab 10&11: Virtual Private Cloud(VPC)in AWS · Jimmy Huang's Blog本周的重点不是单纯“点 AWS 控制台”,而是理解:
什么是 public subnet 和 private subnet
为什么 private EC2 没有 public IP 就不能直接 SSH
Internet Gateway、NAT Instance、Bastion Host 分别解决什么问题
Security Group 和 Network ACL 的区别
为什么 NACL 需要同时配置 inbound 和 outbound rules
为什么 NACL rule number 会影响最终访问结果
Goal
如何手动创建 VPC、subnet、Internet Gateway、route table
如何把 subnet 设计成 public 或 private
如何在不同 subnet 中启动 EC2 instance
如何通过 Security Group 控制 EC2 访问权限
如何通过 Bastion Host 访问 private subnet 中的实例
如何通过 NAT Instance 让 private instance 访问 Internet
如何使用 NACL 进一步控制 subnet 级别的流量
如何解释 Security Group 和 NACL 的核心区别
Task 0: 实验前准备与命名规划
本 Task 主要是先统一本次 Lab 会用到的资源名称、CIDR 范围、替换变量和截图位置。
Step 0.1:确认 AWS 环境
如果你的 AWS Academy 指定了其他 Region,就使用老师要求的 Region,不要强行照抄 us-east-1。
Step 0.2:本次资源命名表
建议你后续都严格使用下面这些名字,方便对照 Lab、截图和排查问题。
Step 0.3:本次文档中的变量替换说明
后面命令里会出现这些占位符,你执行时要替换成自己的真实值。
Step 0.4:最终目标架构
外部电脑可以访问 WebServer01
外部电脑不能直接访问 DatabaseServer
WebServer01 可以访问 DatabaseServer
本地电脑可以通过 WebServer01 作为 Bastion Host 跳转到 DatabaseServer
DatabaseServer 可以通过 Nat_Instance 主动访问 Internet
Internet 不能主动访问 DatabaseServer
Task 1: Building your own VPC
本 Task 要创建本周 Lab 的基础网络环境。
一个 VPC:VPC-demo
两个 subnet:10.0.1.0/24 和 10.0.2.0/24
一个 attached Internet Gateway:MyIGW
一个 public route table:MyPublicRouteTable
10.0.1.0/24 subnet 可以通过 Internet Gateway 访问 Internet
10.0.2.0/24 subnet 暂时仍然保持 private
Step 1.1:理解本次使用的私有 IP 范围
AWS VPC 使用 private IP range 来划分内部网络。常见 private IP 范围包括:
Step 1.2:创建 VPC
不要使用 Launch VPC Wizard,本 Lab 要手动创建和理解每个组件。
Tenancy 选择 Default 的意思是使用 AWS 默认的共享底层硬件。Dedicated tenancy 会使用专用硬件,通常更贵,本 Lab 不需要。
main route table
default Network ACL
default Security Group
Step 1.3:创建 Public Subnet:10.0.1.0/24
这一步创建的是后续的 public subnet。
Step 1.4:创建 Private Subnet:10.0.2.0/24
一个 subnet 不能跨多个 Availability Zone。
所以这里必须选择一个明确的 AZ。为了体现多 AZ 设计,第二个 subnet 最好和第一个 subnet 使用不同 AZ。
Step 1.5:回答实验问题:为什么 /24 subnet 可用地址不是 254 个?
Why is the total number of addresses in each subnet not 254?
一个 /24 subnet 理论上有 256 个 IP 地址。传统网络里通常会认为 network address 和 broadcast address 不能使用,所以可用地址是 254 个。
但是在 AWS VPC 中,每个 subnet 会额外保留 5 个 IP 地址,所以可用数量不是 254,而是 251。
以 10.0.1.0/24 为例,AWS 会保留:
Step 1.6:给 Public Subnet 开启 Auto-assign public IPv4
刚创建出来的两个 subnet 默认可能都没有自动分配 public IP。
现在只给 10.0.1.0/24 开启 public IP 自动分配。
Step 1.7:创建 Internet Gateway
Internet Gateway 的作用是让 VPC 能和 Internet 通信。
创建后,Internet Gateway 默认是 detached 状态,还没有连接到 VPC。
一个 VPC 不能同时 attach 两个 Internet Gateway。
Step 1.8:查看默认 Route Table
但是现在还没有默认路由指向 Internet Gateway,所以 subnet 还不能直接访问 Internet。
Step 1.9:创建 Public Route Table
创建后,新的 route table 不会自动关联 subnet,需要手动 associate。
Step 1.10:给 Public Route Table 添加 Internet Route
如果你的 VPC / Lab 启用了 IPv6,也按 Lab 要求添加:
Step 1.11:把 Public Subnet 关联到 Public Route Table
判断 public subnet 的关键不是名字,而是:
Task 2: Building EC2 Instances in VPC Subnets
本 Task 要在刚刚创建的 VPC 里启动两台 EC2。
在 public subnet 里创建 WebServer01
在 private subnet 里创建 DatabaseServer
给 Web Server 配置 Security Group:WebDMZ
给 DB Server 配置 Security Group:MyDBSG
从 Web Server ping private DB Server
通过 Bastion Host SSH 到 private DB Server
观察 private instance 在没有 NAT 前无法访问 Internet
Step 2.1:创建 Public EC2:WebServer01
选择 Create security group,创建:
Lab 截图里 SSH 通常使用 Anywhere,方便实验
更安全的做法是 SSH source 选择 My IP
HTTP 必须允许 Anywhere,否则浏览器不能从外部访问页面
Step 2.2:创建 Private EC2:DatabaseServer
先选择 existing security group,使用 VPC 的 default security group。
Step 2.3:从本地电脑 SSH 到 WebServer01
如果成功,你会进入 WebServer01 的 Ubuntu terminal。
Step 2.4:创建 DB Security Group:MyDBSG
现在要给 private instance 创建专门的 security group。
为什么 source 是 10.0.1.0/24?
因为我们只希望 public subnet 里的资源访问 private DB,而不是允许整个 Internet 访问它。
Step 2.5:把 DatabaseServer 移到 MyDBSG
Remove default security group
Add MyDBSG
Save
default security group 不应该随便长期用
private subnet 的 instance 应该有独立、明确的访问规则
避免以后有人修改 default security group 影响 private instance
Step 2.6:从 WebServer01 ping DatabaseServer
先在 EC2 Console 里复制 DatabaseServer 的 private IP。
然后确保你已经 SSH 到 WebServer01。
在 WebServer01 terminal 中执行:
DatabaseServer 是否真的在 10.0.2.0/24
MyDBSG 是否允许 All ICMP - IPv4 from 10.0.1.0/24
DatabaseServer 是否已经换到 MyDBSG
两个 subnet 是否都在 VPC-demo
NACL 是否没有被你提前改成 deny
Step 2.7:理解 Bastion Host
Bastion Host 也叫 Jump Box。
在本 Lab 里,WebServer01 可以充当 Bastion Host:
因为 DatabaseServer 没有 public IP,Internet 上的电脑不能直接 SSH 到它。
但是 WebServer01 在同一个 VPC 的 public subnet 里,可以访问 private subnet 中的 DatabaseServer。
Step 2.8:通过 ProxyJump SSH 到 DatabaseServer
建议从本地电脑直接使用 ProxyJump,不要把 .pem 私钥复制到 public EC2 上。
如果需要 agent forwarding,可以先添加 key:
如果你的系统不支持 -J,可以使用 ProxyCommand:
成功后,你会进入 DatabaseServer 的 terminal。
Step 2.9:回答实验问题:在 private EC2 上执行 apt-get update 会发生什么?
What do you think would happen if you do an apt-get update on your private EC2 instance?
在还没有配置 NAT Instance 之前,在 DatabaseServer 上执行:
DatabaseServer 在 private subnet 中:
所以它可以和 VPC 内部资源通信,但不能主动访问 Internet。
在配置 NAT 之前,private EC2 instance 执行 apt-get update 通常会失败,因为它没有 public IP,也没有通过 NAT 访问 Internet 的默认路由。它可以与 VPC 内部的实例通信,但不能直接访问外部 Ubuntu package repository。要让 private instance 主动访问 Internet,需要配置 NAT Instance 或 NAT Gateway。
Task 3: Building a NAT Instance
本 Task 要创建 NAT Instance,让 private subnet 中的 DatabaseServer 可以主动访问 Internet。
创建一个 NAT Instance:Nat_Instance
把 NAT Instance 放在 public subnet
确保 NAT Instance 有 public IP
关闭 NAT Instance 的 Source/Destination Check
在 main route table 里添加 0.0.0.0/0 -> Nat_Instance
测试 private EC2 可以执行 apt-get update
停止 NAT Instance 后再次观察 private EC2 无法访问 Internet
NAT 允许 private instance 主动访问 Internet
NAT 不允许 Internet 主动访问 private instance
NAT Instance 必须在 public subnet 中
NAT Instance 需要关闭 Source/Destination Check
NAT Gateway 不能当 Bastion Host
Step 3.1:理解 NAT Instance 解决什么问题
Step 3.2:创建 NAT Instance
如果你选择的是 arm64 AMI,instance type 也必须支持 ARM,例如 t4g 系列。
如果你使用的是 t2.micro / t3.micro 这类 x86 instance type,就要选择匹配的 x86_64 NAT AMI。
为什么 NAT Instance 必须在 public subnet?
因为 NAT Instance 自己需要通过 Internet Gateway 出去访问 Internet。
如果 NAT Instance 放在 private subnet,它自己也出不去,就无法帮 private EC2 转发流量。
Step 3.3:关闭 Source/Destination Check
但是 NAT Instance 要帮别的 instance 转发流量。
也就是说,NAT Instance 会收到 source / destination 不是自己的流量。
所以必须关闭 Source/Destination Check。
确认状态变成 disabled / stopped。
Step 3.4:确认 WebDMZ 允许来自 private subnet 的流量
因为 Nat_Instance 使用了 WebDMZ security group,所以需要确保 WebDMZ 允许 private subnet 访问 NAT Instance。
如果你在 Task 2 中把 DatabaseServer 从 default security group 移除了,建议给 WebDMZ 添加:
这一步的作用是允许 private subnet 中的 DatabaseServer 把流量发给 NAT Instance。
同时检查 MyDBSG outbound rules:
Step 3.5:在 main route table 中添加 NAT route
现在要让 private subnet 的默认出站流量走 NAT Instance。
选择 main route table,也就是 private subnet 当前默认关联的 route table。
Step 3.6:SSH 到 DatabaseServer 并测试 apt-get update
通过 Bastion Host 进入 DatabaseServer:
Step 3.7:停止 NAT Instance 并验证 Internet 访问失败
然后回到 DatabaseServer,再次执行:
测试结束后,为了后续 Task 继续使用网络,重新启动 NAT Instance:
NAT Gateway 不能当 Bastion Host。
因为 NAT Gateway 是托管网络服务,不是你可以 SSH 登录的 EC2 instance。
Task 4: NACL vs Security Group
本 Task 要比较 Network ACL 和 Security Group。
查看默认 Network ACL
创建新的 Network ACL:MyWebNACL
把 public subnet 关联到 MyWebNACL
观察新 NACL 默认阻止所有流量
安装 Apache 并访问 Hello FIT5225!
添加 NACL inbound / outbound allow rules
测试 NACL rule number 的优先级
对比 NACL 和 Security Group 的区别
Security Group 作用在 instance / ENI 层面
NACL 作用在 subnet 层面
Security Group 是 stateful
NACL 是 stateless
NACL rules 按 rule number 从小到大匹配
第一条匹配的 rule 会决定 allow 或 deny
Step 4.1:查看默认 NACL
默认 NACL 通常允许所有 inbound 和 outbound traffic。
Step 4.2:回答实验问题:NACL rule number 的作用是什么?
Each network ACL rule has a rule number, what is the role of this number?
NACL rule number 决定规则的匹配顺序。AWS 会从最小的 rule number 开始检查规则,一旦找到第一条匹配的规则,就立即应用这条规则的 Allow 或 Deny 结果,不会继续往下检查。
例如,如果 rule 100 允许 HTTP,而 rule 400 拒绝 HTTP,那么 HTTP 仍然会被允许;如果把拒绝规则改成 rule 99,那么拒绝规则会先匹配,HTTP 就会被阻止。
Step 4.3:回答实验问题:rule number 是星号 的默认规则是什么意思?
What does a default rule whose rule number is an asterisk mean?
NACL 中 rule number 为 * 的规则是默认兜底规则。它会在所有编号规则都没有匹配时才生效。通常这条规则表示 deny all,也就是没有被前面规则明确允许的流量都会被拒绝。
这条 * 规则不能编辑或删除,它保证 NACL 最后一定有一个默认处理结果。
Step 4.4:创建新的 Network ACL:MyWebNACL
创建后,查看它的 inbound 和 outbound rules。
新创建的 custom NACL 默认会拒绝所有 inbound 和 outbound traffic,直到你手动添加 allow rules。
Step 4.5:在 WebServer01 上安装 Apache
Step 4.6:把 Public Subnet 关联到 MyWebNACL
Step 4.7:添加 MyWebNACL Inbound Rules
Step 4.8:添加 MyWebNACL Outbound Rules
当外部浏览器访问 Web Server 的 80 端口时,返回流量需要回到客户端的 ephemeral port。
ephemeral port 是客户端临时分配的端口,常见范围是:
Security Group 是 stateful,所以返回流量通常不用额外写规则。
但是 NACL 是 stateless,所以 inbound 和 outbound 都要明确允许。
Step 4.9:重新访问 Web 页面
页面恢复访问
可以再次看到 Hello FIT5225!
Step 4.10:测试 NACL Rule Number 优先级
第一轮:添加 rule 400 deny HTTP
第二轮:把 deny rule 改成 rule 99
Task 5: 收尾与资源清理提醒
如果实验已经完成并且不需要继续展示,建议清理或停止资源,避免产生不必要费用。
Stop 或 Terminate WebServer01
Stop 或 Terminate DatabaseServer
Stop 或 Terminate Nat_Instance
如果不再需要,删除自定义 NACL、Route Table、Internet Gateway、Subnets、VPC
删除 VPC 前需要先 detach Internet Gateway,并删除依赖资源
Summary
本周 Lab 的主线是从零开始搭建一个带有 public subnet 和 private subnet 的 AWS VPC。
一开始我们创建了 VPC-demo,并把 10.0.1.0/24 设计成 public subnet,把 10.0.2.0/24 设计成 private subnet。真正决定 subnet 是否 public 的不是名字,而是它关联的 route table 是否有默认路由指向 Internet Gateway。
然后我们在 public subnet 中创建 WebServer01,在 private subnet 中创建 DatabaseServer。WebServer01 有 public IP,可以从本地电脑直接 SSH;DatabaseServer 没有 public IP,所以不能从 Internet 直接访问。为了访问 private EC2,我们使用 WebServer01 作为 Bastion Host,通过 ProxyJump 跳转进入 private instance。
接着我们创建 NAT Instance,让 private subnet 中的 DatabaseServer 可以主动访问 Internet。NAT 的关键点是:private EC2 可以出去,但外部 Internet 不能主动进来。NAT Instance 必须放在 public subnet 中,并且需要关闭 Source/Destination Check。
最后我们通过 NACL 比较了 subnet 级别和 instance 级别安全控制的区别。Security Group 是 stateful,而 NACL 是 stateless。NACL 需要同时配置 inbound 和 outbound rules,而且 rule number 越小优先级越高,第一条匹配规则会决定最终 allow 或 deny。
本周必须理解的知识点
1. Public Subnet 和 Private Subnet 的区别
2. Internet Gateway 不是自动让所有 subnet 变 public
创建并 attach Internet Gateway 只是第一步。
真正让 subnet 变 public 的条件是:
同时 EC2 还需要 public IP,外部才能直接访问它。
3. Bastion Host 和 NAT Instance 不一样
4. NAT Gateway 不能当 Bastion Host
NAT Gateway 是 AWS 托管服务,不是 EC2 instance。
5. Security Group vs NACL
6. 为什么 NACL 需要 ephemeral ports
因为 NACL 是 stateless,所以返回流量也要被 outbound rules 允许。
否则 inbound 80 开了,网页也可能无法正常返回响应。
Internet
|
Internet Gateway
|
Public Route Table
|
Public Subnet 10.0.1.0/24
|-- WebServer01 / Bastion Host
|-- Nat_Instance
|
Private Subnet 10.0.2.0/24
|-- DatabaseServer
VPC Console
→ Your VPCs
→ Create VPC
VPC Console
→ Subnets
→ Create subnet
VPC Console
→ Subnets
→ Create subnet
256 total addresses - 5 AWS reserved addresses = 251 available addresses
VPC Console
→ Subnets
→ 选择 10.0.1.0/24 subnet
→ Actions
→ Edit subnet settings
→ Enable auto-assign public IPv4 address
→ Save
VPC Console
→ Internet gateways
→ Create internet gateway
选择 MyIGW
→ Actions
→ Attach to VPC
→ 选择 VPC-demo
→ Attach
VPC Console
→ Route tables
→ 找到和 VPC-demo 关联的 main route table
→ Routes
VPC Console
→ Route tables
→ Create route table
MyPublicRouteTable
→ Routes
→ Edit routes
→ Add route
MyPublicRouteTable
→ Subnet associations
→ Edit subnet associations
→ 选择 10.0.1.0/24
→ Save
Subnet route table 有 0.0.0.0/0 -> Internet Gateway
EC2 Console
→ Instances
→ Launch instances
EC2 Console
→ Instances
→ Launch instances
EC2 Console
→ Security Groups
→ Create security group
EC2 Console
→ Instances
→ 选择 DatabaseServer
→ Actions
→ Security
→ Change security groups
本地电脑
|
SSH 到 public IP
|
WebServer01 / Bastion Host
|
SSH 到 private IP
|
DatabaseServer
DatabaseServer
|
Private Subnet
|
没有 public IP
|
不能直接访问 Internet
DatabaseServer
|
Private Route Table
|
Nat_Instance
|
Public Subnet
|
Internet Gateway
|
Internet
EC2 Console
→ Launch instances
AMI Catalog
→ Community AMIs
→ 搜索 owner: 568608671756
→ 选择最新版本的 Feasible Cost Konfigurable NAT / FCK-NAT AMI
nat-nat64-al2023-hvm-1.4.0-20260126-arm64-ebs
这台 instance 发送 / 接收的流量,source 或 destination 是否是它自己
EC2 Console
→ Instances
→ 选择 Nat_Instance
→ Actions
→ Networking
→ Change source/destination check
→ Stop
EC2 Console
→ Security Groups
→ WebDMZ
→ Edit inbound rules
VPC Console
→ Route tables
→ 找到 VPC-demo 的 main route table
Routes
→ Edit routes
→ Add route
private subnet 中不知道往哪里走的 IPv4 Internet 流量,都交给 Nat_Instance
EC2 Console
→ Instances
→ 选择 Nat_Instance
→ Instance state
→ Stop instance
EC2 Console
→ Instances
→ 选择 Nat_Instance
→ Instance state
→ Start instance
VPC Console
→ Network ACLs
→ 找到和 VPC-demo 关联的 Network ACL
Inbound rules
Outbound rules
Subnet associations
VPC Console
→ Network ACLs
→ Create network ACL
VPC Console
→ Network ACLs
→ 选择 MyWebNACL
→ Subnet associations
→ Edit subnet associations
→ 选择 public subnet 10.0.1.0/24
→ Save
MyWebNACL
→ Inbound rules
→ Edit inbound rules
MyWebNACL
→ Outbound rules
→ Edit outbound rules
在 Google 搜索:what is my ip
MyWebNACL
→ Inbound rules
→ Edit inbound rules
VPC 定义大网络范围
Subnet 划分 public / private 区域
Route Table 决定流量往哪里走
Internet Gateway 让 public subnet 连接 Internet
NAT Instance 让 private subnet 主动访问 Internet
Bastion Host 让管理员跳转进入 private subnet
Security Group 控制 instance 级别访问
NACL 控制 subnet 级别访问
该 subnet 关联的 route table 有:
0.0.0.0/0 -> Internet Gateway
Client ephemeral port -> Server port 80
Server port 80 -> Client ephemeral port
ssh -i <KEY_PATH> ubuntu@<WEB_PUBLIC_IP>
ssh -i <KEY_PATH> ubuntu@<WEB_PUBLIC_IP>
ping -c 4 <DB_PRIVATE_IP>
ssh -i <KEY_PATH> -J ubuntu@<WEB_PUBLIC_IP> ubuntu@<DB_PRIVATE_IP>
ssh -A -i <KEY_PATH> -J ubuntu@<WEB_PUBLIC_IP> ubuntu@<DB_PRIVATE_IP>
ssh -o ProxyCommand="ssh -i <KEY_PATH> -W %h:%p ubuntu@<WEB_PUBLIC_IP>" \
-i <KEY_PATH> ubuntu@<DB_PRIVATE_IP>
ssh -i <KEY_PATH> -J ubuntu@<WEB_PUBLIC_IP> ubuntu@<DB_PRIVATE_IP>
ssh -i <KEY_PATH> ubuntu@<WEB_PUBLIC_IP>
apt update && apt install apache2 -y
mv index.html index2.html
echo '<html><h1>Hello FIT5225!</h1></html>' > index.html