RosarioCensabella/secure-vpc-exposure-lab
GitHub: RosarioCensabella/secure-vpc-exposure-lab
一个基于 Terraform 构建的 AWS 安全网络实验室,演示了如何通过 ALB 安全暴露 Web 服务并利用多层防护机制将后端 EC2 实例与公网严格隔离。
Stars: 0 | Forks: 0
# 安全 VPC 暴露实验
## 概述
安全 VPC 暴露实验是一个使用 Terraform 构建的 AWS 网络和云安全作品集项目。
该项目演示了一种安全的暴露模型,其中唯一的应用程序公共入口点是面向互联网的 Application Load Balancer。后端 EC2 应用程序实例运行在私有子网中,没有公有 IPv4 地址,并且仅接受来自 ALB 安全组的应用程序流量。
本实验重点关注:
- AWS VPC 设计
- 公有和私有子网划分
- 路由表验证
- Application Load Balancer 暴露
- 私有 EC2 应用程序托管
- 安全组最小权限原则
- 自定义 Network ACL 行为
- VPC Flow Logs 可观测性
- 功能性暴露验证
- 基于 Terraform 的基础设施配置
## 业务场景
NovaRetail Cloud 是一家虚构的 B2B SaaS 公司,为电子商务客户提供私有的订单管理应用程序。
该公司需要通过公共端点向客户暴露 Web 应用程序,但必须避免将后端应用程序服务器直接暴露给互联网。
工程和安全要求如下:
- 客户必须通过公共端点访问应用程序。
- 后端应用程序服务器必须保持私有。
- EC2 应用程序实例不得具有公有 IPv4 地址。
- 到 EC2 的应用程序流量仅允许来自负载均衡器。
- SSH 不得暴露给互联网。
- 网络流量必须可观测,以便进行验证和故障排除。
- 基础设施必须可使用基础设施即代码重现。
本项目使用 AWS 和 Terraform 实现了这些要求。
## 最终架构
高级流量流:
```
Internet Client
|
| HTTP 80
v
Internet Gateway
|
v
Public Subnets
|
v
Internet-facing Application Load Balancer
|
| HTTP 8080
v
Private Application Subnets
|
v
Private EC2 Application Instances
```
最终环境包括:
- 一个自定义 VPC
- 跨两个可用区的两个公有子网
- 跨两个可用区的两个私有应用程序子网
- 一个 Internet Gateway
- 独立的公有和私有路由表
- 一个面向互联网的 Application Load Balancer
- 端口 80 上的一个 HTTP 监听器
- 转发到 TCP 8080 的一个目标组
- 两个私有 EC2 应用程序实例
- 两个安全组
- 两个自定义 Network ACL
- 传输到 CloudWatch Logs 的 VPC Flow Logs
- 通过 EC2 用户数据部署的精简应用程序
## 网络布局
### VPC
```
VPC name: secure-vpc-exposure-lab-vpc
CIDR: 10.20.0.0/16
```
本项目使用专用的自定义 VPC,而不是 AWS 默认 VPC。
### 子网
| 子网名称 | 类型 | CIDR | 用途 |
|---|---|---|---|
| `secure-vpc-public-a` | 公有 | `10.20.0.0/24` | 可用区 A 中的 ALB 子网 |
| `secure-vpc-public-b` | 公有 | `10.20.1.0/24` | 可用区 B 中的 ALB 子网 |
| `secure-vpc-private-app-a` | 私有 | `10.20.10.0/24` | 可用区 A 中的 EC2 应用程序子网 |
| `secure-vpc-private-app-b` | 私有 | `10.20.11.0/24` | 可用区 B 中的 EC2 应用程序子网 |
公有子网承载 Application Load Balancer。
私有应用程序子网承载 EC2 应用程序实例。
## 路由模型
### 公有路由表
公有路由表包含:
```
10.20.0.0/16 -> local
0.0.0.0/0 -> Internet Gateway
```
这允许公有子网中面向互联网的资源(例如 ALB)与互联网客户端进行通信。
### 私有应用程序路由表
私有应用程序路由表仅包含:
```
10.20.0.0/16 -> local
```
它不包含:
```
0.0.0.0/0 -> Internet Gateway
0.0.0.0/0 -> NAT Gateway
```
这验证了私有应用程序子网没有直接通往互联网的路由。
## 使用的 AWS 服务
| 服务 | 用途 |
|---|---|
| Amazon VPC | 实验的自定义网络边界 |
| 公有子网 | 承载公有 Application Load Balancer |
| 私有子网 | 承载后端 EC2 应用程序实例 |
| Internet Gateway | 为公有子网资源提供互联网路径 |
| Route Tables | 区分公有和私有路由行为 |
| Application Load Balancer | 唯一的公共应用程序入口点 |
| Target Group | 将 ALB 流量路由到 TCP 8080 上的私有 EC2 实例 |
| Amazon EC2 | 运行私有应用程序实例 |
| 安全组 | 强制执行有状态的工作负载级访问控制 |
| Network ACL | 演示子网级的无状态过滤 |
| CloudWatch Logs | VPC Flow Logs 的目标 |
| VPC Flow Logs | 用于可见性和验证的网络元数据日志 |
| IAM | 用于 VPC Flow Logs 传输的专用角色 |
| Terraform | 基础设施即代码配置 |
## 安全设计
核心安全原则是:
```
The ALB is public.
The EC2 application instances are private.
```
### ALB 安全组
安全组:
```
Name tag: sg-secure-vpc-alb
Technical group name: secure-vpc-alb
```
入站规则:
| 协议 | 端口 | 来源 | 用途 |
|---|---:|---|---|
| TCP | 80 | `0.0.0.0/0` | 允许对 ALB 的公共 HTTP 访问 |
出站规则:
| 协议 | 端口 | 目标 | 用途 |
|---|---:|---|---|
| TCP | 8080 | 应用程序安全组 | 将流量转发到私有应用程序实例 |
### 应用程序安全组
安全组:
```
Name tag: sg-secure-vpc-app
Technical group name: secure-vpc-app
```
入站规则:
| 协议 | 端口 | 来源 | 用途 |
|---|---:|---|---|
| TCP | 8080 | ALB 安全组 | 仅允许来自 ALB 的应用程序流量 |
应用程序安全组不允许:
```
TCP 8080 from 0.0.0.0/0
TCP 22 from 0.0.0.0/0
TCP 3389 from any public source
```
最终的应用程序安全组也没有广泛的出站互联网规则。
## 网络暴露模型
| 组件 | 暴露情况 | 原因 |
|---|---|---|
| Application Load Balancer | 公有 | 唯一面向互联网的应用程序组件 |
| EC2 应用程序实例 | 私有 | 部署在私有子网中,没有公有 IPv4 |
| 应用程序端口 8080 | 在 ALB 之后私有 | 只能从 ALB 安全组访问 |
| SSH | 未暴露 | 不存在入站 SSH 规则 |
| RDP | 未暴露 | 不存在入站 RDP 规则 |
| NAT Gateway | 未使用 | 基础实验避免使用 NAT Gateway 以降低成本 |
| VPC Flow Logs | 内部可观测性 | 用于验证网络流量行为 |
## Network ACL 设计
自定义 Network ACL 用于演示子网级的无状态过滤。
### 公有 NACL
```
nacl-secure-vpc-public
```
关联至:
```
secure-vpc-public-a
secure-vpc-public-b
```
关键行为:
- 允许来自互联网的 TCP 80 入站 HTTP 流量。
- 允许发往私有应用程序 CIDR 的 TCP 8080 出站应用程序流量。
- 允许临时返回流量。
- 包含显式拒绝规则。
### 私有应用程序 NACL
```
nacl-secure-vpc-private-app
```
关联至:
```
secure-vpc-private-app-a
secure-vpc-private-app-b
```
关键行为:
- 允许来自公有子网 CIDR 的 TCP 8080 入站流量。
- 允许发往公有子网 CIDR 的临时出站返回流量。
- 包含显式拒绝规则。
由于 Network ACL 是无状态的,因此必须显式允许请求和响应流量。
## 应用层
私有 EC2 实例在 TCP 8080 上运行一个简单的 HTTP 应用程序。
实例:
```
secure-vpc-app-a
secure-vpc-app-b
```
已验证的私有 IP:
```
10.20.10.201
10.20.11.27
```
两个实例都具有:
```
Public IPv4 address: None
```
应用程序使用以下方式部署:
```
app/user-data.sh
```
该脚本在实例本地启动一个最小的 Python HTTP 服务器。在启动期间不需要下载外部包。
### 应用程序端点
| 端点 | 预期响应 |
|---|---|
| `/` | `Secure VPC Exposure Lab - Private Application Instance` |
| `/health` | `OK` |
## Terraform 实现
基础设施使用 Terraform 部署。
主要 Terraform 文件:
```
terraform/
|-- providers.tf
|-- variables.tf
|-- locals.tf
|-- main.tf
|-- vpc.tf
|-- subnets.tf
|-- routes.tf
|-- security-groups.tf
|-- nacl.tf
|-- alb.tf
|-- ec2.tf
|-- flow-logs.tf
|-- iam.tf
`-- outputs.tf
```
应用程序引导脚本存储在:
```
app/user-data.sh
```
Terraform 配置创建了 VPC、子网布局、路由、安全组、NACL、ALB、目标组、EC2 实例、IAM 角色、CloudWatch 日志组和 VPC Flow Logs。
## 关键 Terraform 输出
项目公开了这些 Terraform 输出:
```
vpc_id
public_subnet_ids
private_subnet_ids
alb_dns_name
alb_security_group_id
app_security_group_id
target_group_arn
flow_logs_log_group_name
app_instance_private_ips
```
证据:
```
evidence/screenshots/power-shell/01-terraform-outputs.png
```
## 验证结果
该环境通过 Terraform 输出、AWS CLI 命令、AWS 控制台截图、CloudWatch Logs Insights 和功能性 curl 测试进行了验证。
### 功能性应用程序测试
命令:
```
curl.exe http:///
curl.exe http:///health
```
预期输出:
```
Secure VPC Exposure Lab - Private Application Instance
OK
```
证据:
```
evidence/screenshots/power-shell/17-functional-curl-tests-cli.png
```
### 目标组健康状态
两个 EC2 应用程序实例均已注册到目标组,并在端口 8080 上报告为健康状态。
证据:
```
evidence/screenshots/power-shell/09-target-health-cli.png
evidence/screenshots/aws-console/17-target-group-healthy-targets.png
```
### EC2 私有暴露验证
经验证,EC2 应用程序实例具有私有 IP 地址且没有公有 IPv4 地址。
证据:
```
evidence/screenshots/power-shell/10-ec2-private-instances-cli.png
evidence/screenshots/aws-console/19-ec2-app-a-networking.png
evidence/screenshots/aws-console/20-ec2-app-b-networking.png
```
### 安全组验证
ALB 安全组允许 TCP 80 上的公共 HTTP 访问。
应用程序安全组仅允许来自 ALB 安全组的 TCP 8080 入站流量。
证据:
```
evidence/screenshots/power-shell/11-alb-security-group-cli.png
evidence/screenshots/power-shell/12-app-security-group-cli.png
evidence/screenshots/aws-console/22-alb-security-group-inbound.png
evidence/screenshots/aws-console/23-alb-security-group-outbound.png
evidence/screenshots/aws-console/24-app-security-group-inbound.png
evidence/screenshots/aws-console/25-app-security-group-outbound.png
```
### 路由表验证
私有应用程序路由表不包含通往 Internet Gateway 或 NAT Gateway 的默认路由。
证据:
```
evidence/screenshots/power-shell/05-private-route-table-no-default-route-cli.png
evidence/screenshots/aws-console/07-public-route-table.png
evidence/screenshots/aws-console/09-private-route-table.png
```
### Network ACL 验证
自定义 NACL 已与公有和私有应用程序子网层关联。
证据:
```
evidence/screenshots/power-shell/13-network-acls-cli.png
evidence/screenshots/aws-console/27-public-nacl-associations.png
evidence/screenshots/aws-console/28-public-nacl-inbound-rules.png
evidence/screenshots/aws-console/29-public-nacl-outbound-rules.png
evidence/screenshots/aws-console/30-private-nacl-associations.png
evidence/screenshots/aws-console/31-private-nacl-inbound-rules.png
evidence/screenshots/aws-console/32-private-nacl-outbound-rules.png
```
## 日志记录和可观测性
在 VPC 级别启用了 VPC Flow Logs。
配置:
| 设置 | 值 |
|---|---|
| 资源类型 | VPC |
| 流量类型 | ALL |
| 目标 | CloudWatch Logs |
| 日志组 | `/aws/vpc/secure-vpc-exposure-lab/flowlogs` |
| 保留期 | 7 天 |
证据:
```
evidence/screenshots/power-shell/14-vpc-flow-log-status-cli.png
evidence/screenshots/power-shell/15-cloudwatch-log-group-retention-cli.png
evidence/screenshots/power-shell/16-flow-log-streams-cli.png
evidence/screenshots/aws-console/33-vpc-flow-log-details.png
evidence/screenshots/aws-console/34-cloudwatch-log-group-retention.png
```
CloudWatch Logs Insights 确认了 ALB 节点和私有 EC2 实例之间在 TCP 8080 上被接受的应用程序流量。
证据:
```
evidence/screenshots/aws-console/36-cloudwatch-logs-insights-accept.png
```
观测到的流量模式:
```
10.20.0.x -> 10.20.10.201 TCP 8080 ACCEPT OK
10.20.1.x -> 10.20.11.27 TCP 8080 ACCEPT OK
10.20.10.201 -> 10.20.0.x TCP 8080 ACCEPT OK
10.20.11.27 -> 10.20.1.x TCP 8080 ACCEPT OK
```
## 证据和截图
证据整理于:
```
evidence/screenshots/
|-- aws-console/
`-- power-shell/
```
重要证据包括:
| 证据 | 路径 |
|---|---|
| VPC 详情 | `evidence/screenshots/aws-console/01-vpc-details.png` |
| VPC 资源映射 | `evidence/screenshots/aws-console/02-vpc-resource-map.png` |
| 子网概览 | `evidence/screenshots/aws-console/03-subnets-overview.png` |
| ALB 详情 | `evidence/screenshots/aws-console/11-alb-details.png` |
| ALB 监听器 | `evidence/screenshots/aws-console/14-alb-listener-http-80.png` |
| 目标组健康目标 | `evidence/screenshots/aws-console/17-target-group-healthy-targets.png` |
| EC2 私有实例 | `evidence/screenshots/power-shell/10-ec2-private-instances-cli.png` |
| ALB 安全组 | `evidence/screenshots/power-shell/11-alb-security-group-cli.png` |
| 应用程序安全组 | `evidence/screenshots/power-shell/12-app-security-group-cli.png` |
| VPC Flow Logs 状态 | `evidence/screenshots/power-shell/14-vpc-flow-log-status-cli.png` |
| 功能性 curl 测试 | `evidence/screenshots/power-shell/17-functional-curl-tests-cli.png` |
| Logs Insights ACCEPT 证据 | `evidence/screenshots/aws-console/36-cloudwatch-logs-insights-accept.png` |
截图在需要时已进行涂抹处理,以避免暴露不必要的账户级别标识符。
## 文档
其他项目文档可在以下位置找到:
```
docs/
|-- architecture.md
|-- security-design.md
|-- exposure-validation.md
|-- logging-and-observability.md
`-- troubleshooting.md
```
支持性验证材料可在以下位置找到:
```
tests/
|-- validation-commands.md
`-- expected-results.md
```
流量流详细信息可在以下位置找到:
```
architecture/
`-- traffic-flow.md
```
清理说明可在以下位置找到:
```
cleanup.md
```
## 经验教训
本项目演示了几个实用的 AWS 安全和网络经验教训:
- 仅靠子网名称并不能使工作负载变为私有。
- 私有暴露必须通过路由表、公有 IP 分配和安全规则进行验证。
- ALB 可以是公有的,而后端 EC2 实例保持私有。
- 安全组应表达预期的信任边界。
- Network ACL 需要仔细的双向规则设计,因为它们是无状态的。
- VPC Flow Logs 为流量验证提供了有用的网络级证据。
- Terraform 状态文件绝不能提交到公共存储库。
- 临时的 AWS 凭证在长时间的 Terraform 操作期间可能会过期,需要重新身份验证。
## 存储库结构
```
secure-vpc-exposure-lab/
|-- README.md
|-- cleanup.md
|-- .gitignore
|-- app/
| `-- user-data.sh
|-- architecture/
| `-- traffic-flow.md
|-- docs/
| |-- architecture.md
| |-- security-design.md
| |-- exposure-validation.md
| |-- logging-and-observability.md
| `-- troubleshooting.md
|-- evidence/
| `-- screenshots/
| |-- aws-console/
| `-- power-shell/
|-- screenshots/
| `-- README.md
|-- terraform/
| |-- providers.tf
| |-- variables.tf
| |-- locals.tf
| |-- main.tf
| |-- vpc.tf
| |-- subnets.tf
| |-- routes.tf
| |-- security-groups.tf
| |-- nacl.tf
| |-- alb.tf
| |-- ec2.tf
| |-- flow-logs.tf
| |-- iam.tf
| |-- outputs.tf
| `-- .terraform.lock.hcl
`-- tests/
|-- validation-commands.md
`-- expected-results.md
```
## 成本控制
基础架构有意避免使用 NAT Gateway 以降低成本。
该实验仍会创建计费资源,包括:
- Application Load Balancer
- EC2 实例
- CloudWatch Logs 存储
- VPC Flow Logs 摄入
当不再需要该实验时,请销毁基础设施:
```
cd terraform
terraform destroy
```
请参阅:
```
cleanup.md
```
## 安全和隐私说明
此存储库不包含:
- Terraform 状态文件
- AWS 凭证
- 私钥
- 完整 AWS 账户 ID
- 完整的敏感 ARN
- 密钥或令牌
可以安全展示的技术标识符包括:
- 资源名称
- VPC ID
- 子网 ID
- 安全组 ID
- 实例 ID
- 私有 IP 地址
- 私有 CIDR 范围
- ALB DNS 名称
截图和证据在发布前已视需要进行涂抹处理。
## 项目状态
第一阶段的基础设施和功能验证已完成。
验证的最终状态:
```
Internet user
-> Public Application Load Balancer
-> Private EC2 application instances on TCP 8080
-> VPC Flow Logs evidence in CloudWatch Logs
```
这确认了应用程序可通过 ALB 公开访问,而 EC2 应用层保持私有。
标签:ALB, AWS, B2B SaaS, DevSecOps, DPI, EC2, EC2, ECS, IaC, IaC, Terraform, VPC架构, VPC流日志, 上游代理, 云原生架构, 公有子网, 子网隔离, 安全实验室, 安全模型, 安全组, 应用负载均衡器, 插件系统, 最小特权原则, 架构设计, 流量验证, 电商订单管理, 私有子网, 网络ACL, 网络分割, 网络安全, 网络安全实验, 网络流量分析, 逆向工具, 隐私保护