christiangallon/netflix-secure-streaming-platform
GitHub: christiangallon/netflix-secure-streaming-platform
受 Netflix 启发的零信任 AWS 流媒体安全后端平台,将流量防御、威胁检测与自动事件响应深度集成到流媒体架构中。
Stars: 0 | Forks: 0
# 受 Netflix 启发的安全流媒体与流量防御平台
[](https://developer.hashicorp.com/terraform)
[](https://aws.amazon.com/)
[](https://www.python.org/)
[](https://aws.amazon.com/eks/)
[](https://docs.ansible.com/)
[](#security-controls-matrix)
**领域:** 媒体流媒体 • 云安全与网络工程
**核心亮点:** Zero Trust Networking + 系统韧性 + 分布式系统
## 目录
1. [业务背景与问题描述](#business-context-and-problem-statement)
2. [架构概述](#architecture-overview)
3. [业务影响](#business-impact)
4. [技术栈](#technology-stack)
5. [安全控制矩阵](#security-controls-matrix)
6. [模块分解](#module-breakdown)
7. [部署说明](#deployment)
8. [平台运维](#operating-the-platform)
9. [设计决策与权衡](#design-decisions-and-trade-offs)
10. [作品集亮点](#portfolio-signal)
## 业务背景与问题描述
订阅制流媒体服务的收入建立在两个承诺之上:*流媒体能正常播放* 以及 *内容始终被限制在付费墙内*。这两个承诺往往会在同一个 30 分钟的时间窗口内双双失效——例如重磅大片的点映、体育赛事的决赛、某一地区的首发上线——因为正是在这种时刻,三种压力会同时袭来:
| 压力 | 实际发生的情况 | 业务后果 |
| --- | --- | --- |
| **正常需求激增** | 并发观众数在几分钟内暴增 5 到 20 倍。Manifest 请求的飙升先于 segment 请求,因此当带宽图表发生变化时,平台其实早已处于饱和状态。 | 在本季度最受瞩目的活动中出现缓冲卡顿和播放失败;引发用户流失和退款。 |
| **混杂在激增中的恶意流量** | 凭证填充、manifest 抓取和片段盗取机器人隐藏在这些正常的流量噪音中。天真的自动扩容反而*帮助*了攻击者,因为平台在为他们的流量买单。 | 内容泄露,不断膨胀的出口和计算成本,以及一个永远无法收敛的扩容事件。 |
| **压力之下的操作失误** | 有人为了“让流媒体尽快恢复”,扩大了安全组范围、附加了宽泛的 IAM 策略,或者直接将源站开放到了互联网上。 | 在突发事件期间被永久凿穿的外围防线,且往往在几个月后才被发现。 |
大多数流媒体参考架构仅仅针对吞吐量进行优化。而本项目则将**安全态势、流量激增行为和爆炸半径视为一个紧密耦合的系统**:
* 网络从**架构上即遵循 Zero Trust** —— 划分三个子网层、完全隔离且没有任何互联网路由的数据层、全局禁用 SSH,以及采用默认拒绝的 NACL 和 Kubernetes NetworkPolicies,而不是带有例外的“默认全部允许”。
* 流量防御**在扩容之前就能区分流量激增与攻击**。一个基于 Python 的分类器每五分钟读取一次 CloudWatch 指标,并在“增加容量”、“收紧 WAF”或“进行隔离”之间做出决策——因为这三种应对策略是绝不能互换的。
* 检测机制**与有边界的响应措施紧密绑定**。GuardDuty 的发现结果和基于日志的指标会被送入 Lambda 响应器,从而执行插入 NACL 拒绝规则、收紧速率限制和隔离受损实例等操作——这里的每一项操作都是幂等的、权限受限的,并且在交付时默认开启 `DRY_RUN`。
## 架构概述
### 网络拓扑 —— `10.40.0.0/16`,三层架构 × 三个可用区 (AZ)
```
Internet
│
┌───────────┴────────────┐
│ AWS WAFv2 web ACL │ 10 rules: IP blocklist, geo-block,
│ (regional, on ALB) │ per-IP rate limit, manifest-specific
└───────────┬────────────┘ rate limit, 5 AWS managed rule groups
│
╔════════════════════════════════╪═══════════════════════════════════════════════════╗
║ VPC netflix-stream-prod 10.40.0.0/16 flow logs ─► S3 + CloudWatch Logs ║
║ │ ║
║ ┌─────────────────────────────┴──────────────────────────────────────────────┐ ║
║ │ PUBLIC TIER nacl: public IGW route │ ║
║ │ 10.40.0.0/20 10.40.16.0/20 10.40.32.0/20 (az a / b / c) │ ║
║ │ • Application Load Balancer :443 / :80→redirect │ ║
║ │ • NAT Gateway per AZ (no cross-AZ dependency during an AZ event) │ ║
║ └─────────────────────────────┬──────────────────────────────────────────────┘ ║
║ │ HTTPS :8443 (re-encrypted to origin) ║
║ ┌─────────────────────────────┴──────────────────────────────────────────────┐ ║
║ │ PRIVATE TIER nacl: private (rules 1-99 reserved for auto-block) │ ║
║ │ 10.40.48.0/20 10.40.64.0/20 10.40.80.0/20 (az a / b / c) │ ║
║ │ • EC2 origin Auto Scaling group — nginx, IMDSv2-only, SSM-managed │ ║
║ │ • EKS 1.29 managed node group — streaming API / packager pods │ ║
║ │ • guardduty-processor Lambda (VPC-attached, uses VPC endpoints) │ ║
║ │ • egress only via NAT; no inbound path from the internet │ ║
║ └─────────────────────────────┬──────────────────────────────────────────────┘ ║
║ │ PostgreSQL :5432 (TLS enforced, force_ssl=1) ║
║ ┌─────────────────────────────┴──────────────────────────────────────────────┐ ║
║ │ ISOLATED TIER nacl: isolated ** no route to IGW or NAT ** │ ║
║ │ 10.40.96.0/20 10.40.112.0/20 10.40.128.0/20 (az a / b / c) │ ║
║ │ • Aurora PostgreSQL 15.4 cluster: 1 writer + 2 readers │ ║
║ │ • KMS-encrypted storage, credentials in Secrets Manager (rotatable) │ ║
║ └────────────────────────────────────────────────────────────────────────────┘ ║
║ ║
║ quarantine SG — zero ingress, zero egress. Pre-created so containment is a ║
║ single API call and never requires authoring policy during an incident. ║
╚════════════════════════════════════════════════════════════════════════════════════╝
│ │ │ │
S3 content S3 logs GuardDuty CloudWatch
(SSE-KMS, (AES256, access (detector + S3 / (3 metric filters,
versioned, logs, flow logs, EKS / Malware 12 alarms, 1 composite
TLS-only policy) WAF logs) protection) alarm, 11-widget board)
```
### 检测与响应路径
```
┌──────────────┐ finding ┌───────────────┐ EventBridge ┌──────────────────────┐
│ GuardDuty ├─────────────►│ EventBridge ├────────────────►│ guardduty-processor │
└──────────────┘ sev ≥ 4.0 │ rule │ │ (Lambda) │
└───────────────┘ └──────────┬───────────┘
│
NACL DENY in reserved window 1-99 ◄──────────────────────────────────────┤
WAF IP-set entry ◄─────────────────────────────────────────────────────── │
SNS + Slack notification ◄────────────────────────────────────────────────┘
┌──────────────┐ every 5 min ┌──────────────────────┐ SURGE ► emergency scale-out
│ CloudWatch ├─────────────►│ traffic-monitor ├── ABUSE ► notify, do NOT scale
│ metrics │ │ (Lambda) ├── DEGRADED ► page on-call
└──────────────┘ └──────────────────────┘ HEALTHY ► publish metrics only
┌──────────────┐ hourly ┌──────────────────────┐
│ S3 access ├─────────────►│ content-access- ├──► 6 detectors: VOLUME, REQUEST_RATE,
│ logs │ │ auditor (Lambda) │ ENUMERATION, AFTER_HOURS,
└──────────────┘ └──────────────────────┘ ACCESS_DENIED_SPIKE, WEAK_TLS
┌──────────────┐ one-click ┌──────────────────────┐
│ on-call / ├─────────────►│ threat-response ├──► isolate → tag → forensic snapshots
│ runbook 1.1 │ (DRY_RUN │ (Lambda) │ → revoke IAM sessions → SNS report
└──────────────┘ by default)└──────────────────────┘
```
## 业务影响
**1. 在高需求事件中保护高级内容和订阅用户的信任。**
Manifest 和 segment 的 endpoint 拥有各自独立的 WAF 速率限制,源站集群配有专用的紧急扩容策略,而 S3 内容访问审计器能够检测到普通的 4xx 监控仪表盘容易忽略的枚举和片段盗取行为。在那些决定本季度业绩的关键活动中,付费墙依然稳固,流媒体持续流畅播放。
**2. 通过自动化监控,减少因滥用或配置失误引发的爆炸半径。**
每一层网络均为默认拒绝;数据层根本没有互联网路由可供错误配置。基于日志的指标过滤器和 12 个 CloudWatch 警报能在几分钟内,将权限提升尝试、流日志拒绝激增和违规片段请求飙升转化为告警通知;此外,预置的隔离安全组和权限受限的取证 IAM 角色将故障遏制变成了一项边界清晰、可供审查的标准操作,而非慌乱中的临时起意。
**3. 使云网络与系统韧性与安全的平台工程保持一致。**
同一套 Terraform 代码同时定义了网络边界、工作负载、检测控制措施和警报——因此安全态势和系统容量可以在同一个 Pull Request 中一并审查。Ansible 以幂等方式执行主机加固,Kubernetes NetworkPolicies 在集群内部映射了 VPC 的分层结构,并且每个警报都关联了一个带编号的运维手册章节,使得响应流程如同基础设施一样经过了严谨的工程设计。
## 技术栈
| 层级 | 技术 | 在本平台中的作用 |
| --- | --- | --- |
| 基础设施即代码 | **Terraform 1.9+**, AWS provider ~> 5.60 | 网络、工作负载、检测和警报的唯一事实来源。Provider 版本通过 `.terraform.lock.hcl` 中的哈希值锁定。 |
| 网络 | **Amazon VPC**、子网、路由表、**NACL**、NAT 网关、VPC endpoint | 跨 3 个可用区的三层 Zero Trust 拓扑;不包含任何出口路由的隔离数据层。 |
| 边界防御 | **AWS WAFv2**、**Application Load Balancer** | 包含 10 条规则的 Web ACL:IP 黑名单、地域封锁、基于 IP 的全局速率限制和针对 manifest 的特定速率限制、5 个 AWS 托管规则组。在 ALB 处终止 TLS 并重新加密后发送至源站。 |
| 访问控制 | **安全组** (包含 `quarantine`) | 仅使用基于安全组引用的规则——各层之间禁止使用 CIDR 白名单,全局禁用任何 SSH 入站。 |
| 计算 (虚拟机) | **Amazon EC2** + Auto Scaling 组、启动模板 | nginx 源站集群,强制要求 IMDSv2,使用加密的 EBS 卷,模板变更时触发 Instance Refresh。 |
| 计算 (容器) | **Amazon EKS 1.29** + 托管节点组 | 流媒体 API / 打包器工作负载;仅限私有的 API endpoint,针对密钥采用信封加密。 |
| 编排策略 | **Kubernetes** manifests | Pod Security Admission 设为 `restricted`,配置 5 个 NetworkPolicies,HPA 自动扩容范围 3→40 个副本,配置 PodDisruptionBudget。 |
| 数据 | **Amazon Aurora PostgreSQL 15.4** | 位于隔离层的 Writer 节点 + 2 个 Reader 节点;开启 `rds.force_ssl=1`,使用 KMS 静态加密,通过 Secrets Manager 管理凭证。 |
| 对象存储 | **Amazon S3** | 内容存储桶 (SSE-KMS,开启版本控制,强制使用 TLS 的存储桶策略) 和日志存储桶 (用于服务器访问日志、流日志、WAF 日志)。 |
| 身份 | **AWS IAM** | 遵循最小权限原则的实例/Lambda 角色,针对 Pod 使用 IRSA,配置打破玻璃机制的 `incident_responder` 角色。 |
| 威胁检测 | **Amazon GuardDuty** | 开启了 S3、EKS 审计日志、EKS 运行时和恶意软件保护的检测器;配置了针对已知良性噪音的抑制过滤器。 |
| 可观测性 | **CloudWatch** Logs/Metrics/Alarms/Dashboard、**EventBridge**、**SNS**、**SQS** DLQ | 3 个日志指标过滤器,12 个警报,1 个名为 `platform_under_attack` 的复合警报,包含 11 个小组件的 Dashboard。 |
| 配置管理 | **Ansible** (`aws_ec2` 动态清单, `aws_ssm` 连接) | 无需 SSH 的主机配置:流媒体角色、遵循 CIS 标准的加固角色、监控代理 playbook。 |
| 自动化 | **Python 3.12** (仅使用 boto3 和标准库) | 四个响应器:GuardDuty 处理器、流量分类器、威胁遏制模块、内容访问审计器。 |
## 安全控制矩阵
| # | 控制措施 | 实现方式 | 位置 | 预防的故障模式 |
| --- | --- | --- | --- | --- |
| 1 | 托管式威胁检测 | GuardDuty 检测器,15 分钟发布频率,开启 S3 + EKS 审计 + EKS 运行时 + 恶意软件保护,配置抑制过滤器 | `terraform/guardduty.tf` | 受损的实例 / 挖矿程序 / 凭证外泄长时间未被察觉。 |
| 2 | 自动化安全发现分诊 | EventBridge 规则 → `guardduty-processor` Lambda → 执行 NACL DENY 拦截 + WAF IP 集 + SNS/Slack 告警 | `terraform/guardduty.tf`, `python/guardduty_processor.py` | 安全发现仅仅躺在凌晨 3 点无人问津的控制台里。 |
| 3 | Web 应用防火墙 (WAF) | WAFv2 Web ACL:IP 黑名单、地域封锁、2 条基于速率的规则,应用 AWS Common / KnownBadInputs / IpReputation / SQLi / Linux 规则组,以及匿名 IP 应对策略 | `terraform/waf.tf` | L7 洪水攻击、抓取、注入以及 TOR/代理滥用直达源站。 |
| 4 | 网络 ACL (子网级,无状态) | 3 组 NACL;**私有 NACL 将规则编号 1–99 专门保留**,用于自动化拒绝拦截 | `terraform/vpc.tf` | 在事件处理中途自动化脚本与人工争抢规则编号;避免了在安全组之上缺乏有效的粗粒度拦截节点。 |
| 5 | 安全组 (实例级,有状态) | ALB→origin, origin→Aurora, EKS 控制平面↔节点之间全部采用安全组引用;**零规则的 `quarantine` 安全组**;**全局不存在任何端口 22 的规则** | `terraform/security_groups.tf` | 横向移动,以及突发事件下急需遏制时却要临时编写新策略。 |
| 6 | 隔离的数据层 | Aurora 子网所用的路由表中**既没有 IGW,也没有 NAT 路由** | `terraform/vpc.tf`, `terraform/aurora.tf` | 彻底杜绝数据库数据外泄的路径,即使某个安全组被错误放大。 |
| 7 | 禁止交互式 SSH | 仅允许 SSM Session Manager;Ansible 使用 `aws_ssm` 建立连接;安全加固角色**直接禁用 `sshd`** 并将其拉黑 | `ansible/roles/security/tasks/main.yml` | 密钥泛滥、堡垒主机以及未被记录的 Shell 访问。 |
| 8 | IAM 最小权限 | 按工作负载划分角色,使用资源 ARN 和条件键代替 `*`,Pod 采用 IRSA,作用域受限的紧急备用 `incident_responder` 角色 | `terraform/iam.tf` | 权限过大的角色在任何系统被攻破后,反而成为实际的爆炸半径。 |
| 9 | 静态加密 | 对 S3 内容、EBS、Aurora、EKS 密钥、CloudWatch Logs 使用支持自动轮换的客户托管 KMS 密钥;日志存储桶使用 AES256 (日志投递主体无法使用 CMK) | `terraform/s3.tf`, `aurora.tf`, `eks.tf`, `ec2.tf` | 快照/备份/对象被直接泄露。 |
| 10 | 传输中加密 | ALB 启用 TLS 1.3 策略,到源站 `:8443` 的 HTTPS 重加密,`rds.force_ssl=1`,S3 强制执行 `aws:SecureTransport` 拒绝策略 | `terraform/ec2.tf`, `aurora.tf`, `s3.tf` | VPC 内部出现明文传输的 manifest/segment/数据库查询。 |
| 11 | 实例元数据保护 | 强制开启 `http_tokens = required` (IMDSv2),跳数限制为 1;Kubernetes NetworkPolicy 拒绝访问 `169.254.169.254` | `terraform2.tf`, `kubernetes/network-policy.yaml` | 针对凭证的 SSRF 攻击,这是流媒体边缘典型的泄露路径。 |
| 12 | Pod 级别的 Zero Trust | Pod Security Admission 设为 `restricted`,非 root 用户运行,根文件系统只读,弃权 Linux capabilities,5 个默认拒绝的 NetworkPolicies | `kubernetes/*.yaml` | 单个被攻破的 Pod 蔓延至数据层或元数据服务。 |
| 13 | 审计与流量可见性 | 将 VPC Flow Logs → S3 + CloudWatch,S3 服务器访问日志,ALB 访问日志,WAF 日志,EKS 控制平面日志,开启配置了不可变规则集 (`-e 2`) 的 `auditd` | `terraform/vpc.tf`, `s3.tf`, `waf.tf`, `ansible/roles/security` | 突发事件后调查时缺乏任何证据。 |
| 14 | 基于日志的检测 | 针对违规片段激增、权限提升尝试和流日志拦截记录配置的指标过滤器 | `terraform/cloudwatch.tf` | 那些永远不会触犯托管规则的隐蔽攻击。 |
| 15 | 区分流量激增与恶意滥用 | `traffic_monitor.py` 分类器:识别为 SURGE 则自动扩容,**明确识别为 ABUSE 则绝不扩容** | `python/traffic_monitor.py` | 盲目扩容导致为攻击者的流量买单。 |
| 16 | 有边界的遏制策略 | `threat_response.py`:替换为 quarantine 安全组 → 打标签 → 创建 `CreateSnapshots` → 吊销会话,全流程幂等,默认 `DRY_RUN=true`,需加 `--execute` 才会实际执行 | `python/threat_response.py` | 自动化脚本引发比威胁本身更严重的宕机故障。 |
| 17 | 内容访问分析 | `content_access_auditor.py`:基于请求者和源 IP,在 S3 访问日志上执行 6 种行为检测器 | `python/content_access_auditor.py` | 在大量 4xx 噪音掩护下,安静且缓慢的内容窃取行为。 |
| 18 | 供应链 / 漂移控制 | 提交并锁定 `.terraform.lock.hcl`,锁定 boto3 版本范围,在应用任何配置前执行 `nginx -t` 和 `sshd -t` 进行语法验证 | 覆盖全代码库 | 默默发生的 Provider 漂移;糟糕的模板导致整个集群全面瘫痪。 |
## 模块分解
### `terraform/` — 基础设施与检测控制
| 文件 | 内容 |
| --- | --- |
| `providers.tf` | AWS provider ~> 5.60,默认标签,包含被注释掉的 S3 + DynamoDB 远程状态后端。 |
| `main.tf` | `locals` (命名前缀、可用区/CIDR 计算、标签映射),调用方身份和可用区数据源。 |
| `variables.tf` | 30 个带有验证块的类型化变量 (检查 CIDR 格式、可用区数量限制为 2–3、阈值设置以及 `enable_automated_containment` 开关)。 |
| `outputs.tf` | 网络/工作负载/数据/安全相关的输出,`kubeconfig_command`,`ansible_dynamic_inventory_filter`,以及包含可直接复制粘贴的安全态势检查命令的 `verification_commands` 映射。 |
| `vpc.tf` | VPC,9 个子网,IGW,每个可用区独立的 NAT,3 套路由表,3 组 NACL (其中私有 NACL 预留了 1–99),将流日志传送到 S3 + CloudWatch,网关/接口型 VPC endpoint。 |
| `security_groups.tf` | 定义 ALB、origin、EKS 集群/节点、Aurora、Lambda、VPC endpoint 以及 `quarantine` 安全组 —— 全部采用安全组引用规则,彻底消灭 SSH。 |
| `iam.tf` | 源站实例角色 (SSM + 受限的 S3 权限 + 指标上报),Lambda 执行角色,EKS 集群/节点角色,OIDC Provider + IRSA 角色,包含 forensic-snapshot 和紧急扩容权限、打破玻璃机制的 `incident_responder` 角色。 |
| `s3.tf` | 内容存储桶 (SSE-KMS,版本控制,生命周期管理,强制 TLS 策略,屏蔽公开访问) 和日志存储桶 (AES256,日志投递策略,保留生命周期)。 |
| `ec2.tf` | 启动模板 (强制 IMDSv2,加密 EBS,内嵌 `templates/streaming_bootstrap.sh.tftpl`),配置了实例刷新的 ASG,ALB + HTTPS 侦听器 + 目标组,包含 `emergency_scale_out` 在内的 3 种扩缩容策略。 |
| `eks.tf` | EKS 1.29 集群 (私有 endpoint,密钥信封加密,开启所有控制平面日志类型),托管节点组,核心插件,访问条目。 |
| `aurora.tf` | 位于隔离层的 Aurora PostgreSQL 15.4 集群,1 个 writer + `aurora_reader_count` 个 reader,带有 `force_ssl` 设置的参数组,由 Secrets Manager 管理的主密钥,增强监控,Performance Insights。 |
| `guardduty.tf` | 检测器 + 各种保护功能 + 抑制过滤器,EventBridge 规则,SNS 主题 + 邮件订阅,SQS DLQ,以及四个 Lambda 函数及其日志组。 |
| `waf.tf` | 区域级 Web ACL (包含 10 条规则),托管 IP 黑名单集,内部白名单集,将 WAF 日志投递到 `aws-waf-logs-*`。 |
| `cloudwatch.tf` | 3 个日志指标过滤器,12 个指标警报,`platform_under_attack` 复合警报,以及包含 11 个组件的运维 Dashboard。每个警报描述都明确引用了运维手册的章节号。 |
| `terraform.tfvars.example` | 带有详细注释、可安全复制使用的变量值示例文件。 |
### `kubernetes/` — 集群内的 Zero Trust
| 文件 | 内容 |
| --- | --- |
| `namespace.yaml` | `streaming` 命名空间,开启 Pod Security Admission `restricted` 模式,包含标注了 IRSA 的 Service Account、ResourceQuota、LimitRange。 |
| `streaming-deployment.yaml` | 源站 Deployment (包含 nginx 应用端口 `:8080`,指标端口 `:9090`),非 root 用户运行,根文件系统只读,探针配置,拓扑分布约束,以及两个 ConfigMap。 |
| `streaming-service.yaml` | ClusterIP 服务,Headless 指标服务,以及配置了注解以挂载 WAF Web ACL 的 ALB Ingress。 |
| `hpa.yaml` | HorizontalPodAutoscaler 配置 (3→40 个副本),采用非对称的扩容/缩容行为 (迅速扩容,缓慢缩容)。 |
| `network-policy.yaml` | 5 条策略:默认拒绝所有 ingress+egress,允许 ALB 入站,允许 DNS 出站,基于 CIDR 限制数据层出站,以及显式拒绝访问 IMDS。 |
| `pod-disruption-budget.yaml` | 设置 `minAvailable: 67%`,确保节点轮换期间绝不会压垮播放系统的可用容量。 |
### `ansible/` — 无需 SSH 的主机配置
| 文件 | 内容 |
| --- | --- |
| `ansible.cfg` | 配置 `aws_ec2` 清单插件,`profile_tasks` 回调,JSON 事实缓存,取消主机密钥提示。 |
| `inventory/hosts.yml` | 根据 `tag:Project` + `tag:ManagedBy=terraform` + `running` 进行过滤的动态清单,并使用 `role_/env_/az_/type_` 作为键控组。 |
| `inventory/group_vars/all.yml` | 从环境中继承的共享身份标识、子网 CIDR、端口、CloudWatch 命名空间/日志组、SSM 存储桶和目标组 ARN。 |
| `playbooks/streaming_server.yml` | 按 `serial: 25%` 进行滚动部署,`max_fail_percentage: 0`,依次执行:ALB 取消注册 → 配置更新 → 重新注册 → 等待 `healthy` 状态。 |
| `playbooks/security_hardening.yml` | 在执行前后捕获安全态势,按 `serial: 33%` 执行加固角色,运行后进行健康检查,输出 `HardeningRunCompleted` 指标。 |
| `playbooks/monitoring_agent.yml` | 配置 CloudWatch Agent (收集指标 + 4 个日志流),并在加固过的 systemd unit 下运行 node_exporter 1.8.2。 |
| `roles/streaming/` | 依赖包,Service Account,自签的源站 TLS 证书 + `ffdhe2048` 组,应用 `nginx.conf.j2` 时使用 `validate: nginx -t -c %s` 进行校验,配置 logrotate,各种 handlers 以及 HTTP 验证。 |
| `roles/security/` | 移除遗留的软件包,应用 `sshd_config.j2` (通过验证后,直接彻底禁用 `sshd`),约 30 项 sysctl 控制,内核模块黑名单,配置 `limits.d`,配置包含不可变规则集的 `auditd`,设置 umask/cron/banner 控制,并在带有 `assert` 门控的情况下收集证据。 |
### `python/` — 检测与响应自动化
| 文件 | 内容 |
| --- | --- |
| `guardduty_processor.py` | 标准化 EventBridge *和* SNS 信封格式,从 `service.action` 中提取远端 IP,通过逻辑判断 `is_blockable` (跳过私有/RFC-5737/内部网段),在预留的 1–99 窗口中插入 NACL DENY 规则 (内含 LRU 淘汰和并发竞争处理),最后通过 `urllib` 向 SNS 和 Slack 发送通知。 |
| `traffic_monitor.py` | 通过一次 `get_metric_data` API 调用执行 9 个查询;将状态分类为 SURGE (激增) / ABUSE (滥用) / DEGRADED (降级) / HEALTHY (健康);仅在状态为 SURGE 时触发 `emergency_scale_out`;发布派生的自定义指标。 |
| `threat_response.py` | 幂等遏制流程:将实例的 SG 替换为 `quarantine` → 打标签 → 调用 `CreateSnapshots` 获取取证快照 → 依据 `aws:TokenIssueTime` 注入 `AWSRevokeOlderSessions` 拒绝策略以吊销 IAM 会话 → 发送 SNS 报告。默认开启 `DRY_RUN=true`;命令行需明确传入 `--execute` 方可执行。 |
| `content_access_auditor.py` | 利用正则解析器处理 S3 服务器访问日志,构建基于 (请求者, IP) 的行为画像,内置 6 种检测器 (VOLUME, REQUEST_RATE, ENUMERATION, AFTER_HOURS, ACCESS_DENIED_SPIKE, WEAK_TLS),单次扫描上限为 2000 个对象,若超限则通过 `coverage.truncated` 状态上报。 |
| `requirements.txt` | 锁定 boto3/botocore 的版本范围,并说明了采用“零额外依赖”设计的理由。 |
每个模块都支持**离线运行**:各自都包含一个使用合成数据进行的 `__main__` 自测功能,此外,所有 AWS 客户端都被封装在 `_LazyClient` 代理中,因此在引入模块时绝不会强制要求配置 region 或提供凭证。
```
python3 python/guardduty_processor.py # envelope parsing + is_blockable table
python3 python/traffic_monitor.py # 4 classification scenarios
python3 python/content_access_auditor.py # parses 301 synthetic log lines, 5 detectors fire
python3 python/threat_response.py --help # containment CLI (requires --execute to act)
```
### `docs/`
| 文件 | 内容 |
| --- | --- |
| `architecture.md` | 涵盖拓扑结构、请求路径、检测流水线、数据流向、故障域分析、容量扩缩模型。 |
| `runbook.md` | 按照顺序编号的响应操作流程 (1.1 – 5.1),一一对应所有的 CloudWatch 警报说明,并包含灾难恢复 (DR) 和扩缩容操作流程。 |
## 部署说明
### 前置条件
| 工具 | 版本 | 说明 |
| --- | --- | --- |
| Terraform | ≥ 1.9.0 | Provider 哈希值已在 `.terraform.lock.hcl` 中锁定。 |
| AWS CLI | ≥ 2.15 | 配置具备创建 VPC/EKS/RDS/IAM 等资源权限的凭证。 |
| kubectl | ≥ 1.29 | 次版本号必须与 EKS 集群版本差距在一个发布周期以内。 |
| Ansible | core ≥ 2.16 | 需额外安装 `amazon.aws` collection 以及 `boto3`/`botocore` Python 库。 |
| Python | 3.12 | 用于编译 Lambda 源码以及在本地运行自测程序。 |
| Session Manager plugin | 最新版本 | Ansible 的 `aws_ssm`接插件必须依赖此组件。 |
```
ansible-galaxy collection install amazon.aws community.general
pip install -r python/requirements.txt
```
### 1. 配置平台基础设施
```
cd terraform
cp terraform.tfvars.example terraform.tfvars
# 编辑:aws_region、security_alert_emails、trusted_admin_cidrs、blocked_country_codes。
terraform init
terraform validate
terraform plan -out=tfplan # review the plan; it is not a formality here
terraform apply tfplan
```
`terraform apply` 将创建 VPC 及其三层架构、ALB + WAF、源站 ASG、EKS 集群、Aurora 集群、GuardDuty、全部四个 Lambda 函数以及完整的警报和 Dashboard 集合。
预计耗时约 20–25 分钟,其中大部分时间花在配置 EKS 和 Aurora 上。
### 2. 获取其他部署层所需的输出
```
export AWS_REGION=$(terraform output -raw aws_region)
export ANSIBLE_SSM_BUCKET=$(terraform output -raw logs_bucket)
export TARGET_GROUP_ARN=$(terraform output -raw target_group_arn)
terraform output verification_commands # copy-paste posture checks
```
### 3. 配置源站集群 (无 SSH,仅使用 SSM)
```
cd ../ansible
ansible-inventory --graph # confirm discovery
ansible-playbook playbooks/security_hardening.yml --check # dry run first
ansible-playbook playbooks/security_hardening.yml
ansible-playbook playbooks/streaming_server.yml # rolling, ALB-aware
ansible-playbook playbooks/monitoring_agent.yml
```
### 4. 部署 Kubernetes 工作负载
```
cd ..
eval "$(cd terraform && terraform output -raw kubeconfig_command)"
kubectl apply -f kubernetes/namespace.yaml
kubectl apply -f kubernetes/network-policy.yaml # deny-by-default BEFORE workloads
kubectl apply -f kubernetes/streaming-deployment.yaml
kubectl apply -f kubernetes/streaming-service.yaml
kubectl apply -f kubernetes/hpa.yaml
kubectl apply -f kubernetes/pod-disruption-budget.yaml
kubectl -n streaming rollout status deploy/streaming-api
```
### 5. 验证安全态势
```
cd terraform
terraform output -json verification_commands | jq -r 'to_entries[] | "\(.key):\n \(.value)\n"'
```
该校验映射包含一系列检查:确认 `quarantine` 安全组依然保持零规则,私有 NACL 的 1–99 拦截窗口完好无损,遏制模块依然保持在 `DRY_RUN` 状态,GuardDuty 已开启全部保护功能,以及确认全局没有任何一个安全组暴露了 22 端口。
### 6. 安全地演练响应器程序
```
# 在不更改任何内容的情况下对当前流量进行分类。
aws lambda invoke --function-name netflix-stream-prod-traffic-monitor \
--payload '{}' /dev/stdout
# 可疑实例的遏制计划 - 仅打印,不执行 (DRY_RUN=true)。
aws lambda invoke --function-name netflix-stream-prod-threat-response \
--payload '{"instance_ids":["i-0123456789abcdef0"]}' /dev/stdout
```
### 环境销毁
```
cd terraform
terraform destroy # set aurora_deletion_protection = false first
```
只要存储桶中还有对象,`terraform destroy` 就不会直接删除开启了版本控制的内容存储桶——这是刻意设计的保护机制。请务必手动清空它,而不是贪图方便让 IaC 直接删掉这些核心内容资源。
## 平台运维
* **Dashboard** —— 运行 `terraform output dashboard_url` 即可打开包含 11 个组件的 CloudWatch 仪表盘:请求速率,4xx/5xx 错误率,p95 播放延迟,源站 CPU,ASG 容量与最大值对比,WAF 拦截与放行对比,按严重程度划分的 GuardDuty 发现,流日志拒绝记录,以及 Lambda 健康度。
* **警报 → 运维手册** —— 每一个警报描述的结尾都附带了对应的 runbook 章节编号。`docs/runbook.md` 也严格按照这些编号 (1.1 – 5.1) 进行组织排版,因此当告警电话响起时,你能立刻知道应该翻开哪一页。
* **复合警报** —— `platform_under_attack` 仅在错误/延迟信号与安全信号同时爆发时才会被触发。这种组合特征正是区分“一次糟糕的发版”与“真实攻击”的关键所在,它也是整个系统中唯一被允许在凌晨 3 点把人从睡梦中叫醒的警报。
## 设计决策与权衡
| 决策 | 被否决的替代方案 | 原因 |
| --- | --- | --- |
| **每个可用区部署独立的** NAT 网关 | 共用一个 NAT 网关 | 共用 NAT 会导致所有可用区的出口都依赖于某一个可用区。为这种以绝对高可用为核心价值的平台支付微薄的额外小时费,买来的是各个可用区相互独立的故障域。 |
| 采用**预置型** Aurora writer + 2 个 reader 节点 | Aurora Serverless v2 | 流媒体元数据的负载特征是“基线高、且叠加突发洪峰”;预置型实例能提供可预测的 p99 性能,并且方便在每个可用区分别安置 Reader 节点。(此外,在 Provider 中这两种配置也是互斥的。) |
| 源站通信在 **:8443** 端口上**重新加密** | 从 ALB 到源站直接使用明文 HTTP | 在 Zero Trust 模型中,“VPC 内部”并不被视为信任边界。相比于海量的 segment I/O 所消耗的资源,这点 CPU 加解密开销根本不值一提。 |
| 使用 **NACL** 拒绝规则进行自动化拦截 | 仅依靠安全组拦截 | 安全组本身不支持拒绝语义。NACL 提供了无状态的、子网级别的流量拦截节点,而且预留 1–99 规则号段的做法,巧妙避免了自动化程序与人工运维在规则配置上互相冲突。 |
| 遏制 Lambda 默认**需手动确认** | 只要触发任何发现就自动隔离 | 一次误报就会导致线上业务源站被迫下线。通过 Runbook 指引手动点击一次执行既非常迅速,又能留下清晰的审计记录。 |
| 日志存储桶使用 **AES256**,而不使用 CMK | 全局统一使用 CMK | AWS 中有部分日志投递主体无法通过客户托管密钥 (CMK) 写入日志。强行使用一把无法生效的密钥加密,只会默默切断整个审计证据链——这是比不加密更糟的后果。 |
| **彻底消灭 SSH** (直接禁用 `sshd`) | 加固 SSH + 堡垒主机 | SSM Session Manager 提供了全程留痕、受 IAM 授权控制且无需密钥的访问方式。直接移除该守护进程,能从根本上消灭相关的攻击面以及令人头疼的密钥轮换问题。 |
| Python 响应器**仅使用标准库 + boto3** | 使用 requests / 第三方 SDK | Lambda 运行时本身就内置了 boto3。坚持零额外依赖,意味着既不需要额外构建 Lambda Layer,也避免了在处理突发事件的响应代码中引入供应链被污染的潜在风险。 |
## 作品集亮点
### Zero Trust Networking + 系统韧性 + 分布式系统
**Zero Trust Networking。** 系统边界并不是单一的防火墙,而是一套由多重控制组合而成的防御体系:包含三个子网层,且数据层被完全隔离、*没有任何* 通往互联网的路由;NACL 和安全组全部默认拒绝;全面采用安全组引用规则而不是 CIDR 白名单;强制执行 IMDSv2 并通过 Kubernetes 显式拒绝对 `169.254.169.254` 的访问;确保每一跳的数据传输都启用了 TLS (包括 ALB→origin 以及 应用→Aurora);IAM 角色严格通过资源 ARN 和条件键进行权限界定;并且在整个资产环境中彻底禁用了交互式 SSH 访问。这里的信任是基于每一个身份和每一条数据流分别授予的,而且所有流量均被完整记录。
**系统韧性。** 流量激增时的系统表现是经过严密设计保障的,而不是靠运气祈祷:配置了按 AZ 独立划分的 NAT 网关、跨三个 AZ 的子网、拥有专属紧急扩容策略的 ASG、能够“快扩慢缩”的 HPA、保障在节点轮换期间依然能保留三分之二播放容量的 PodDisruptionBudget,以及一个“宁可报警也不帮恶意负载扩容”的流量分类器。12 个常规警报和 1 个复合警报,将各项响应流程汇聚到一本运维手册中,各项操作章节的编号甚至被直接嵌入到了警报定义里。
**分布式系统。** 整个平台跨越了 EC2、EKS、Aurora、S3 和 Lambda 等多种服务,横跨三个可用区。平台上的自动化代码完全是为这一复杂的分布式现实量身打造的:包括幂等的威胁遏制操作、带驱逐机制且能防范并发竞争的 NACL 规则分配、针对事件投递配置的 SQS 死信队列 (DLQ)、具备明确扫描上限并通过 `truncated` 字段如实报告覆盖率的扫描器,以及能够在发布时自动从 ALB 摘除节点并重新注册的滚动式 Ansible 部署流程;更重要的是,所有的响应器程序均默认采用 `DRY_RUN` 模式。这些应对措施专门解决那些只有在分布式系统规模庞大时才会暴露的边角失效场景,并且它们是在代码层面得到了切实解决,而不是仅仅停留在注释里的设想。
**作者:** Christian Gallon — 云安全工程师 / DevOps 工程师
**代码库:** `netflix-secure-streaming-platform`
标签:Ansible, AWS, DPI, ECS, EKS, Terraform, 云原生架构, 子域名突变, 流媒体后端, 漏洞探索, 系统提示词, 自动化响应, 逆向工具, 零信任网络