CDN回源返回403而直连正常,主因是防盗链误拦——CDN未透传原始Referer或Nginx未正确读取;需日志验证Referer值、改用X-Original-Referer头校验、白名单含业务域名及空Referer,并结合CDN IP段做双重判断。

遇到 CDN 回源后资源返回 403,但直连源站正常,大概率是防盗链规则把合法回源请求误拦了——根本原因不是 Nginx 配置错了,而是 CDN 没把真实 Referer 传过来,或者 Nginx 没用对头去校验。
确认 CDN 是否透传了原始 Referer
别假设 CDN 默认会传,得验证。最直接的方法是临时在 Nginx 日志里加 Referer 字段,看回源请求到底带了什么:
- 修改 log_format,加上 $http_referer 和 $http_x_original_referer(如果 CDN 支持该头)
- 重启 Nginx,触发一次 CDN 缓存失效并访问一个图片资源
- 查 access.log,重点看回源 IP(比如阿里云 CDN 通常是 100.64.0.0/10 段)对应的 Referer 值:
→ 如果是空、https://cdn.example.com 或其他 CDN 自身域名,说明没透传;
→ 如果是用户真实来源页(如 https://blog.com/article),说明已透传,问题出在 Nginx 校验逻辑
检查 Nginx 是否读取了正确的 Referer 头
CDN 回源时,它自己就是“客户端”,$http_referer 默认读的是 CDN 节点的 Referer(即它自己的域名),不是浏览器原始 Referer。必须显式指定信任的头:
- 优先使用 CDN 提供的自定义头,比如 X-Original-Referer 或 X-Real-Referer(需在 CDN 后台配置回源请求头:把客户端 Referer 写入该字段)
- Nginx 配置中改用 $http_x_original_referer 替代 $http_referer 做校验
- 如果 CDN 不支持自定义头,且确认它确实原样转发了标准 Referer,则仍可用 $http_referer,但要确保 valid_referers 白名单里包含你允许的真实业务域名,而不是自己的源站域名
校验逻辑是否适配 CDN 回源特征
直接套用 valid_referers server_names 会失败,因为回源请求的 Referer 是 CDN 域名,不是你的业务域名:
- 只对静态资源路径启用校验,例如 location ~* \.(jpg|png|js|css)$,避免影响 HTML 或 API 接口
- valid_referers 白名单应包括:
→ 业务主站及子域名(example.com *.example.com)
→ 允许空 Referer(none,应对直接访问或某些客户端策略)
→ 可选:CDN 自身域名(如 cdn.example.net),仅当它稳定且可信时 - 不要把 blocked 当万能兜底,它只匹配被防火墙/代理剥离协议的 Referer(如 //example.com),对 HTTPS→HTTP 场景才有效,多数 CDN 不适用
配合 CDN IP 白名单做双重判断(更稳妥)
单纯依赖 Referer 容易被伪造或丢失,结合 CDN 回源 IP 段可大幅提升可靠性:
- 从 CDN 厂商文档查清其回源出口 IP 段(如腾讯云 CDN 回源 IP 有固定列表,阿里云提供 CIDR)
- 在 Nginx 中用 geo 或 map 指令标记 CDN IP,例如:
geo $cdn_ip {
default 0;
100.64.0.0/10 1;
} - 在校验逻辑中组合判断:
→ 若请求来自 CDN IP,则跳过 Referer 检查,直接放行
→ 否则,再走正常的 valid_referers 校验流程


















