详解自建高防 CDN 应对伪造 Host 攻击的安全校验逻辑
摘要:# 别让伪造Host攻击,把你自建的高防CDN打穿 前两天跟一个做游戏的朋友聊天,他愁得不行。自己花了不少钱搭了一套高防CDN,结果半夜被一波“看起来很正常”的请求给打挂了。查了半天日志,发现源站的CPU和带宽都还好,但就是服务不可用。最后揪出来,是攻击…
别让伪造Host攻击,把你自建的高防CDN打穿
前两天跟一个做游戏的朋友聊天,他愁得不行。自己花了不少钱搭了一套高防CDN,结果半夜被一波“看起来很正常”的请求给打挂了。查了半天日志,发现源站的CPU和带宽都还好,但就是服务不可用。最后揪出来,是攻击者伪造了Host头,请求直接绕过了CDN的防护规则,精准地砸在了源站的薄弱环节上。
他当时就懵了:“我CDN都上了,IP也隐藏了,怎么还能被打到源站?”
说实话,这种场景你应该不陌生吧?很多团队在自建高防CDN时,注意力都放在了流量清洗、CC防护这些“大炮”上,却往往忽略了像Host头校验这种“门锁”级别的细节。结果就是,攻击者不用蛮力,轻轻一撬,门就开了。
今天,咱就抛开那些宏大的架构图,专门聊聊自建高防CDN里,怎么设计一套扎实的安全校验逻辑,专门防住这种“伪造Host攻击”。说白了,就是给你的CDN后门,再加把牢靠的锁。
伪造Host攻击:你以为的“正常请求”,其实是把钥匙
首先,咱得把这事儿讲明白。Host头是HTTP协议里一个再基础不过的字段,它告诉服务器:“我客户端的这个请求,是想访问哪个域名(或IP+端口)。”
在标准的CDN工作流程里:
- 用户访问
www.yourgame.com - DNS把解析指向你的高防CDN节点IP
- CDN节点收到请求,Host头是
www.yourgame.com - CDN根据这个Host,去自己的配置里找到对应的源站IP,然后转发请求
- 源站回复内容,CDN缓存并返回给用户
看起来很安全,对吧?源站IP对用户是隐藏的。
但攻击者会这么干:
- 他直接扫描或猜测到你的CDN节点IP(这其实不难,很多节点IP并非绝对机密)。
- 他构造一个HTTP请求,但手动把Host头改成你的源站真实IP,或者一个你源站上绑定的、但没公开的域名(比如内网管理地址
admin.internal.com)。 - 他把这个请求,海量地发向你的CDN节点。
问题来了:如果你的CDN节点配置是“无脑转发”,或者校验规则太宽松,它看到这个Host头,就会去自己的映射表里找。如果没找到 admin.internal.com 这个域名的配置,它可能会:
- 错误地将请求转发给默认源站(可能就是你的真实业务源站)。
- 或者,更糟糕的是,如果你的CDN程序逻辑有漏洞,攻击者甚至能通过精心构造的Host,让请求直接穿透CDN,抵达源站。
结果就是,攻击流量没有经过CDN的任何清洗策略,直接怼到了源站服务器上。你的高防CDN,形同虚设。
自建高防CDN,你的校验逻辑“配齐”了吗?
很多开源CDN方案或者自己写的转发模块,默认配置真的挺“裸奔”的。光有转发功能,没有安全校验,等于在互联网上裸泳。
下面这几个校验逻辑,是必须打上的“补丁”。别嫌麻烦,真被打的时候,这就是救命的。
第一把锁:强制校验“业务域名”白名单
这是最核心、最有效的一步。在你的CDN边缘节点上,必须配置一个明确的、允许转发的域名白名单。
- 具体怎么做:在Nginx(假设你用Nginx做边缘)里,别只用
server_name来区分。对于转发到源站的location块,用if或map指令,对$host变量进行白名单匹配。 -
代码示例(Nginx思路):
# 定义一个白名单变量映射,或使用if判断(注意if的效率,生产环境建议用map) map $host $allowed_domain { default 0; ~^www\.yourgame\.com$ 1; ~^api\.yourgame\.com$ 1; ~^static\.yourgame\.com$ 1; # 只把你公开对外的业务域名加进来 } server { listen 80; server_name _; # 捕获所有域名请求 location / { if ($allowed_domain != 1) { # 直接返回444(连接关闭)或403,记录日志告警 return 444; # access_log /var/log/nginx/host_attack.log; } # 只有Host在白名单的请求,才进行后续的CDN处理和转发 proxy_pass http://your_origin_upstream; proxy_set_header Host $host; # 保持原始Host } } - 大实话:这就好比小区门卫,他只认识本小区业主的名单。你报一个陌生名字或者隔壁小区地址,他根本不会给你开门,更不会帮你联系户主。
第二把锁:剥离或重写可疑的Host头
攻击者可能会玩花样,在请求里塞入多个Host头,或者在一些非标准的头部字段(如 X-Forwarded-Host、X-Real-IP 等)里做手脚。如果你的后端源站信任了这些头部,就可能被绕过。
- 具体怎么做:在CDN节点转发给源站之前,主动清理一遍请求头。
- 移除所有非你主动设置的
X-Forwarded-Host、X-Real-IP等字段。 - 确保只传递一个、且经过你白名单校验的Host头给源站。
- 移除所有非你主动设置的
- 关键点:源站也应该只信任来自CDN节点的特定头部(比如一个自定义的、带签名的头部
X-CDN-Auth: [加密令牌]),而不是直接信任客户端传来的任何信息。
第三把锁:给源站也穿上“铠甲”
别把鸡蛋全放在一个篮子里。CDN是第一道防线,源站自己也得有点自保能力。
- 源站防火墙策略:在源站服务器的防火墙(如iptables、云安全组)上,只允许你的高防CDN节点IP段访问。把“仅允许CDN回源”这个策略,从软件配置落实到网络层。这是最物理的隔离。
- 源站Web服务器配置:在源站的Nginx/Apache上,也配置一遍
server_name。只响应来自CDN的、Host头为业务域名的请求。对于其他Host的请求,直接丢弃或返回错误。这叫纵深防御。
一个真实的“翻车”案例与补救
我去年看过一个电商站点的配置,他们的自建CDN用了开源软件。为了“灵活”,在边缘节点配置了 server_name _; 并且没有做任何Host过滤,转发规则是基于URL路径前缀来的。
攻击者发现了这一点。他们用工具批量伪造请求:
GET /api/userInfo HTTP/1.1
Host: 10.0.0.1 (这是他们猜到的源站内网IP)
...
这些请求全部被CDN节点接收,并因为路径匹配 /api/ 规则,被转发到了源站集群。源站的内网应用看到Host是 10.0.0.1,以为是正常的内部服务调用,就正常处理了。攻击者利用这个接口的漏洞,疯狂刷券。直到运营发现异常券码暴增,才追查到问题。
他们的补救措施,就是立刻加上了上面说的第一把锁(域名白名单),并且紧急在源站防火墙封掉了非CDN节点的所有IP(除了运维通道)。立竿见影,伪造Host的流量瞬间清零。
最后说几句实在的
自建高防CDN,技术成就感很高,成本也可能更优,但安全是一个细节堆砌起来的工程。伪造Host攻击只是众多“旁路攻击”手法中的一种,但它恰恰打在了很多自建系统“重功能、轻校验”的软肋上。
别以为上了高防就万事大吉。定期做安全审计,模拟攻击者视角,用工具扫一下你的CDN边缘IP,试试伪造不同的Host头看看响应。监控日志里那些返回444/403的请求,它们可能就是攻击的蛛丝马迹。
安全这东西,很多时候不是比谁家的盾更厚,而是比谁家的门缝更窄。把Host头校验这类“小门缝”堵严实了,你的自建高防CDN,才能真正称得上“高防”。
行了,思路就聊这么多。赶紧去检查一下你的配置文件吧,说不定真有惊喜(吓)呢。

