Python
云计算
悠悠
2026年5月31日

源站 IP 暴露被直接打穿?这套 AWS 纵深防御方案你一定用得上

上周半夜接到一个紧急电话,客户的业务挂了。打开监控一看,源站 ALB 的 CPU 直接拉满,连接数爆表。但奇怪的是 CloudFront 那边的请求量完全正常,WAF 日志也干干净净。

我当时就猜到了——源站 IP 漏了,攻击者绕过了 CloudFront 直接打源站。后来确认就是这样,客户的源站域名之前在 DNS 里解析过公网 IP,虽然后来改成了 CloudFront 的 CNAME,但历史记录在 SecurityTrails 上一查就有,攻击者拿这个 IP 直接对着 ALB 开干,CloudFront 上的 WAF 规则再多也没用,因为流量根本没经过 CloudFront。

这事儿让我觉得有必要把源站防护这个话题好好聊一聊。很多人觉得 CDN 前面挂个 WAF 就安全了,其实这只是第一道门,源站本身还在互联网上裸奔呢。

你以为的安全,其实只防了一半

我见过太多团队的架构是这样的:CloudFront 挂 WAF,后面接一个公网 ALB,ALB 后面是 ECS/EKS。WAF 规则配了一堆,IP Rate Limiting、Geo Block、Bot Control 全上了,看起来铜墙铁壁。

但你想想,WAF 防的是什么?是经过 CloudFront 的流量。攻击者如果直接找到你源站的公网 IP 或域名,绕过 CloudFront 直接访问 ALB,你的 WAF 规则一条都匹配不上。

找源站 IP 的手段多得很,我随便列几个:

  • DNS 历史记录——你以前解析过的 IP 全留着呢,SecurityTrails 这种工具一搜就有
  • 证书透明度日志——你申请 SSL 证书的时候域名信息就公开了
  • Shodan、Censys 这种全网扫描引擎,端口 Banner 证书一把梭
  • 还有各种泄露场景,邮件头里带源站 IP 的、API 返回值里暴露内网信息的、甚至有把源站域名硬编码在前端 JS 里的……

有人可能会说,那我源站前面也挂一个 WAF 不就行了?CDN 一层、源站一层,双重保险。我以前也这么想过,后来发现根本行不通。

源站 WAF 最大的问题是分不清谁是谁。 经过 CDN 转发过来的请求,TCP 源 IP 是 CDN 节点的地址,真实客户端 IP 在 X-Forwarded-For 里。而直连源站的请求,TCP 源 IP 就是攻击者自己的,X-Forwarded-For 可以随便编。这两种请求搅在一起,WAF 就抓瞎了——按 TCP 源 IP 限速吧,CDN 节点的 IP 就那么几个,正常用户的请求也全被限了;按 X-Forwarded-For 限速吧,直连请求伪造这个头部跟玩一样。结果就是误报漏报一大堆,运维成本翻倍,效果约等于零。

所以思路得变:别在应用层纠结了,直接在网络层或传输层把非 CDN 流量掐死。

两条路,看你走哪条

我根据实际项目经验,总结了两种落地方案:

你的场景推荐方案一句话概括
用了好几家 CDN,源站在 AWSmTLS 双向认证靠证书验明正身,谁有证谁进来
只用 CloudFront,源站在 AWSVPC Origin源站从互联网上消失,谁都找不到

下面详细拆解。

先说简单的:VPC Origin,让源站隐身

如果你的架构只用 CloudFront 一家 CDN,那 VPC Origin 是最省心也最安全的方案,没有之一。

原理其实很直白:把源站放到 VPC 私有子网里,不给它公网 IP,不给它公网域名。CloudFront 通过 AWS 内部的 ENI(弹性网络接口)直接连到你的私有子网,流量走的是 AWS 内网,不经过互联网。攻击者连目标都发现不了,更别提攻击了。

传统架构下源站是有公网 IP 的:

Client → CloudFront → ALB (公网IP,暴露了)
Attacker ─────────────→ ALB (绕过CDN直接打)

VPC Origin 架构下源站没有公网 IP:

Client → CloudFront ──ENI──→ ALB (私有子网,无公网IP)
Attacker ────────── ✗ ─────→ 不可达,根本找不到

打个不太恰当的比方,传统架构相当于你家大门装了监控(WAF),但房子就在马路边上,谁都能看到门牌号。VPC Origin 相当于把你家搬到了一个没有门牌号的地下室,只有知道暗道的人(CloudFront)才能进来,外人连你住哪都不知道。

配置过程

前提条件有几个要注意的:

  • VPC 得挂上 Internet Gateway,这是 AWS 的技术实现要求。别担心,这只是个标识,实际不会有互联网流量通过 IGW 到达私有子网,你的源站还是安全的
  • 源站必须在私有子网里,不能有 NAT Gateway,不能有 Internet 路由
  • 支持 ALB、NLB、EC2 实例

创建 VPC Origin:

aws cloudfront create-vpc-origin \
  --vpc-origin-endpoint-config \
    Name=my-vpc-origin,\
    Arn=arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-private-alb/abc123,\
    HTTPSPort=443,\
    OriginProtocolPolicy=https-only

配置安全组,限制只有 CloudFront 能进来:

方式一,用 CloudFront Managed Prefix List:

aws ec2 authorize-security-group-ingress \
  --group-id sg-origin-xxx \
  --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,PrefixListIds=[{PrefixListId=pl-3b927c52}]

方式二,用 CloudFront 托管安全组,这个限制更严格,只允许 CloudFront 的 ENI 访问:

aws ec2 authorize-security-group-ingress \
  --group-id sg-origin-xxx \
  --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,UserIdGroupPairs=[{GroupId=sg-cloudfront-vpc-origins-xxx}]

我个人更推荐方式二,限制粒度更细。

把 VPC Origin 关联到 Distribution 就简单了,在 CloudFront 控制台的 Origin 配置里选你刚创建的 VPC Origin 资源就行。

踩坑提醒:

  • gRPC 和 Lambda@Edge Origin 触发器不支持,如果你的业务用了这些得另想办法
  • IPv6-only 子网不行
  • NLB 做 VPC Origin 时不支持 TLS Listener,需要 TLS 终结的话得用 ALB
  • 部署大概要等 15 分钟,别急
  • 支持跨账户共享,通过 AWS RAM 实现,多团队协作时很方便

DDoS?不存在的

VPC Origin 最让我舒坦的一点就是——源站根本不在公网上,DDoS 从何谈起?所有面向互联网的流量 CloudFront 接着,CloudFront 自带 AWS Shield Standard,L3/L4 的基础防护就有了。你不用额外买 Shield Advanced,不用在源站做任何 DDoS 防护配置。省钱省心。

再说复杂的:mTLS,多 CDN 场景的刚需

如果你的业务同时用了 CloudFront + Cloudflare,或者还加了 Akamai,源站都在 AWS 的 ALB 后面——这在出海业务里太常见了,国内走一家 CDN,海外走 CloudFront,合规要求还得再加一家。这种多 CDN 架构下,VPC Origin 就用不了了(它只认 CloudFront),得靠 mTLS。

为什么不是其他方案?

我知道有人会想到这几种方案,我逐个说说为什么不行:

Security Group 白名单——限制源站只允许 CDN 的 IP 段访问。能用,但 CDN 的 IP 段动辄几百个,Security Group 有 IP 数量限制容易超。而且 CDN 的 IP 范围会变,你得盯着更新,运维负担不小。IP 理论上还能被伪造。

自定义 Header——CDN 回源时加个 X-My-Secret: abc123,源站校验这个 Header。简单是简单,但 Header 可以被抓包截获,也可以被伪造,安全性太低。一旦泄露就完了。

Direct Connect 专线——安全倒是安全,但每个 CDN 厂商拉一条专线,成本高得吓人,开通周期还长,灵活性差。

mTLS 优势在哪? 认证发生在 TLS 握手阶段,比应用层早得多。就像你进小区,自定义 Header 是到了单元门口才查门禁卡,mTLS 是在小区大门口就验身份证——连小区都进不来,更别说单元门了。

具体来说:

  • 传输层就完成身份认证,应用层没法伪造
  • 每个 CDN 用自己的客户端证书,源站 Trust Store 统一管理
  • 证书轮换可以平滑做,不影响业务
  • 想断某个 CDN 的访问?删掉对应的 CA 证书就行

架构长这样

                    ┌─────────────────────────────────────────────┐
                    │              AWS Cloud                       │
┌──────────┐       │  ┌───────────────┐      ┌──────────────┐   │
│CloudFront│──mTLS──▶│  ALB (mTLS)   │─────▶│  EC2 / ECS   │   │
│(CDN #1)  │       │  │  Trust Store  │      │   (源站)      │   │
└──────────┘       │  └───────────────┘      └──────────────┘   │
┌──────────┐       │         ▲                                   │
│Cloudflare│──mTLS──────────┘                                    │
│(CDN #2)  │       │                                             │
└──────────┘       │                                             │
┌──────────┐       │                                             │
│ Akamai   │──mTLS──────────┘                                    │
│(CDN #3)  │       │                                             │
└──────────┘       └─────────────────────────────────────────────┘

三家 CDN 各自带自己的客户端证书回源,ALB 的 Trust Store 里存了三家的 CA 证书,有证的放行,没证的 TLS 握手阶段就拒了。

配置实操

以 CloudFront + ALB 为例走一遍完整流程,其他 CDN 原理一样,只是 CDN 侧证书出示的方式不同。

CloudFront 侧:让 CloudFront 出示客户端证书

几个前提条件别漏了:

  • CloudFront 定价计划得是 Business、Premium 或 Pay As You Go,免费版不支持
  • 客户端证书要存到 ACM,而且必须在 us-east-1(CloudFront 的老规矩)
  • 证书的 EKU 属性必须是 TLS Client Authentication,不然 CloudFront 不认

CLI 配置:

aws cloudfront update-distribution \
  --id E1EXAMPLE \
  --distribution-config '{
    "Origins": {
      "Items": [{
        "Id": "my-alb-origin",
        "DomainName": "origin.example.com",
        "CustomOriginConfig": {
          "HTTPSPort": 443,
          "OriginProtocolPolicy": "https-only"
        },
        "OriginMtlsConfig": {
          "ClientCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/abc-123"
        }
      }]
    }
  }'

注意几个点:同一个 Distribution 的不同 Origin 可以配不同的客户端证书,挺灵活的。但不兼容 VPC Origins、gRPC、WebSocket 和 Lambda@Edge Origin 触发器,用了这些功能的得另想办法。还有如果源站不要求客户端证书,CloudFront 不会主动出示,连接照常走,这个行为是合理的。

ALB 侧:验证客户端证书

ALB 的 mTLS 有两种模式。Passthrough 模式是 ALB 不验证证书,把证书链通过 Header 传给后端让后端自己验。Verify 模式是 ALB 用 Trust Store 直接验证,通过才放行。

我强烈建议用 Verify 模式。Passthrough 把验证逻辑推给后端应用,增加复杂度还容易出漏洞。能在基础设施层解决的事别推到应用层。

Verify 模式配置:

创建 Trust Store,上传所有授权 CDN 的 CA 证书:

aws elbv2 create-trust-store \
  --name cdn-trust-store \
  --ca-certificates-bundle-s3-bucket my-certs-bucket \
  --ca-certificates-bundle-s3-key ca-bundle.pem

修改 ALB Listener 启用 mTLS:

aws elbv2 modify-listener \
  --listener-arn arn:aws:elasticloadbalancing:... \
  --mutual-authentication Mode=verify,TrustStoreArn=arn:aws:elasticloadbalancing:...:truststore/cdn-trust-store

ALB 在 Verify 模式下会自动注入一些 Header,可以用于后端审计和细粒度授权:

Header内容
X-Amzn-Mtls-Clientcert-Serial-Number证书序列号
X-Amzn-Mtls-Clientcert-Issuer颁发者
X-Amzn-Mtls-Clientcert-Subject主题
X-Amzn-Mtls-Clientcert-Validity有效期
X-Amzn-Mtls-Clientcert-Leaf叶子证书

比如你想区分请求是从 CloudFront 来的还是 Cloudflare 来的,看 Issuer 就行。做审计日志的时候也方便。

多 CDN 证书管理——运维的大头

配完了只是开始,证书的日常管理才是真正的考验。

ALB Trust Store 支持在一个 CA bundle 文件里放多个 CA 证书,只要 CDN 出示的客户端证书是 bundle 中任一 CA 签发的,ALB 就放行。不同 CDN 的证书签发方式不一样:

CDN签发方式CA 证书怎么拿
CloudFront自建 Private CA 签发,导入 ACMaws acm-pca get-certificate-authority-certificate
CloudflareZone-level AOP 用自建 CA;Global AOP 用 Cloudflare 公共 CAauthenticated_origin_pull_ca.pem
AkamaiAkamai-signed 或 Third-party CAControl Center → CDN → mTLS Origin Keystore

证书轮换我推荐"双 CA 并存"策略:先把新 CA 加到 bundle 里更新 Trust Store,等所有 CDN 节点都切到新证书了,再把旧 CA 从 bundle 里移除。整个过程零中断,不用停业务。

撤销访问更简单,从 Trust Store 里移除对应 CDN 的 CA 证书,立刻阻断该 CDN 的回源连接。比如你跟某家 CDN 解约了,删掉它的 CA 证书就完事了。

mTLS 架构下的 DDoS 防护

mTLS 方案有个不得不面对的问题:源站 ALB 还是暴露在公网上的。虽然只有持合法证书的请求能通过 TLS 握手,但 L3/L4 层的网络攻击不需要完成 TLS 握手就能消耗资源。

L7 层的攻击(HTTP Flood、CC 之类的)mTLS 天然免疫——攻击者没有合法的客户端证书和私钥,TLS 握手都完不成,HTTP 请求根本发不出来。

但 L3/L4/L5 层(SYN Flood、UDP 反射、TLS 握手洪泛)需要 AWS Shield Advanced 来扛。Shield Advanced 在 AWS 网络边缘就把攻击流量清洗掉了,ALB 根本感知不到。一个月 $3,000,不便宜,但高价值业务该花还是得花。

两种方案到底怎么选

直接看对比:

mTLSVPC Origin
安全性高,传输层认证最高,网络层隔离
多 CDN❌ 只认 CloudFront
源站公网暴露还是需要公网域名完全没有
DDoS 防护L7 天然免疫,L3/L4 要 Shield Advanced天然免疫,不需要额外防护
证书管理要管不需要
部署难度中等
兼容性限制不支持 VPC Origin/gRPC/WebSocket不支持 gRPC/Lambda@Edge
成本mTLS 免费,Shield Advanced 可选 $3,000/月无额外费用

我的建议是:能用 VPC Origin 就用 VPC Origin,配置简单安全性最高还不用管证书。只有确实需要多 CDN 的场景才上 mTLS,但证书轮换的运维成本你得提前有心理准备。

简单画个决策流程:

用了多家 CDN?
├── 是 → mTLS,没得选
└── 否 → 只用 CloudFront?
    ├── 是 → VPC Origin,最省心
    └── 否 → 看看其他 CDN 有没有 mTLS 能力

最后说两句

源站防护这事儿,核心就一句话:让 CDN 成为源站的唯一入口,在网络层或传输层把非法直连掐死。 别在应用层折腾 WAF 规则了,越往底层做越靠谱。

多 CDN 用 mTLS,TLS 握手阶段就验身份,伪造不了。纯 CloudFront 用 VPC Origin,源站从互联网上消失,攻击者连地址都找不到。不管哪种,都比"双 WAF"或者 IP 白名单强太多。

安全防护这东西,永远是在和攻击者比谁更底层——你在应用层做规则匹配,人家在网络层绕过你;你在网络层封堵,他就更难搞了。把防线往下沉,才是正道。


公众号:耕云躬行录

个人博客:躬行笔记

觉得有用的话,关注 @运维躬行录,转发给还在用"双 WAF"方案的朋友们看看。后面还会继续分享 AWS 网络和安全方面的实战踩坑,咱们下回聊。

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码