如何配置Apache实现有效的热链接防护防止资源盗用

来源:Nodejs社区作者:松松建站头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何配置Apache实现有效的热链接防护防止资源盗用》,敬请观看详情。有没有遇到过服务器带宽突然飙升,打开访问日志发现一堆来自陌生域名的图片请求?你的网站资源正在被其他站点直接“借用”,这就是热链接。Apache 作为服务器端的第一道防线,提供了 mod_rewrite 和 SetEnvIf 两大利器来阻断这种偷梁换柱的行为。不过,粗放的拦截规则常常误伤搜索引擎爬虫,甚至让正常用户打开空白页。这篇文章从 Referer 头的检测原理出发,详细拆解两种主流配置方案,分析空白 Referer 的成因与处理技巧,最后给出一套兼顾安全与体验的完整配置。如果你的图片、视频或下载资源正在被无偿使用,不妨动手试试这些方法。

如何配置Apache实现有效的热链接防护防止资源盗用

热链接是怎样偷走你的带宽的

当浏览器请求一个页面时,HTTP 请求头中会带有一个 Referer 字段,用以告诉服务器当前请求是从哪个页面跳转过来的。如果一个网站 A 在自己的 HTML 中直接使用 <img src="https://ippipp.com/pic.jpg"> 的形式嵌入网站 B 的图片,那么当用户访问网站 A 时,浏览器向网站 B 发送的图片请求会带上 Referer: https://www.siteA.com/page.html。服务器 B 由此就能判断,这个请求并非来自本站的页面,而是被其他网站所引用——这就是典型的热链接,也就是俗称的盗链。

对小型站点而言,几张图片被引用可能无伤大雅;但如果你的服务器上存放了大量高清图片、CSS 样式文件或视频资源,被流量较大的网站直接“搬运”,你的服务器就会白白承担大量的带宽开销,页面加载速度反而变慢,而原站点的内容创作者却没有获得任何展示和回报。更极端的情况下,一些爬虫程序会不断抓取你的静态资源,造成服务器的严重负载。因此,在 Apache 层面设置热链接保护,是平衡资源安全与访问效率的重要手段。

需要注意的是,Referer 头的可靠程度并不高。出于隐私保护或安全策略,某些浏览器、防火墙或者隐私插件会主动移除或篡改 Referer 字段,当用户从 HTTPS 页面跳转到 HTTP 资源时,Referer 也会被默认屏蔽。这些场景下请求会把空 Referer 发送到服务器,如果规则过于严格,会将正常用户拒之门外。所以,一个严谨的热链接防护方案既要能识别异常来源,又要给空白 Referer 留出合理的放行通道。

用 mod_rewrite 搭建第一道防盗链防线

如果你的 Apache 已经开启了 mod_rewrite 模块,通过 .htaccess 或虚拟主机配置文件编写改写规则,是实施热链接保护最灵活的方式。它的核心思路是:检查 HTTP_REFERER 变量的值,如果发现是从不允许的域名发起的请求,或者来自特定类型的爬虫,就对该请求进行重定向或直接禁止。

下面是一段最基础的防盗链配置,它的作用是:当请求以 .jpg、.jpeg、.png、.gif 结尾的图片时,如果 Referer 为空,或者 Referer 中的域名不以 yourdomain.com 结尾,就将请求重定向到一张“请勿盗链”的提示图片上。

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yourdomain.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?another-allowed.com [NC]
RewriteRule .(jpg|jpeg|png|gif)$ https://yourdomain.com/images/nohotlink.jpg [R,L]

这里需要逐条理解 RewriteCond 的逻辑。第一条 !^$ 表示“Referer 不是空字符串”,这意味着如果请求不包含 Referer 头,这条条件为真,但下面一条限制不被满足时就会触发拦截。第二条 !^http(s)?://(www.)?yourdomain.com 意思是“Referer 不以你的域名开头”(忽略大小写),满足这条条件时说明请求来自外部网站。多个 Cond 之间默认是 AND 关系,所以只有当 Referer 不为空且不属于你的域名时,重写规则才会生效。如果你有多个环境或备用域名,比如 CDN 域名、www 和非 www 都需要放行,就用多条 Cond 罗列出来。

但是,上面这个例子显然没有考虑空白 Referer 的情况。如果用户直接从地址栏打开图片链接,或者使用隐私浏览器,Referer 为空,这条规则会将其重定向到 nohotlink.jpg,这显然不是我们所期望的。常见的处理方式是:允许空白 Referer 直接放行,需要把第一条 RewriteCond 反转或结合其他条件。下面这种写法更为常见:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?yourdomain.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?search-engine.com [NC]
RewriteRule .(jpg|jpeg|png|gif|svg|webp)$ - [F,L]

这里变化在于最后一条 RewriteRule 使用了 [F,L] 标志。F 表示返回 403 Forbidden,禁止访问而不做重定向。这比返回一张提示图片更简洁,也能节省一次额外的 HTTP 请求。而对于空白 Referer,由于第一条 RewriteCond!^$,当 Referer 为空时,这条条件不满足,整个条件组合为假,重写规则就不会触发,请求会正常响应。一些搜索引擎在抓取图片时,Referer 可能是 search-engine.com 的形式,你也可以像示例那样额外允许。

基于 SetEnvIf 与 Require 的轻量化方案

除了 mod_rewrite,Apache 还可以利用 SetEnvIf 指令结合访问控制来实现防盗链。这种方法不需要重写引擎,配置相对简单,并且能直接与 Apache 的 Require 指令配合,特别适合仅需限制特定文件类型的场景。

其原理是:用 SetEnvIfNoCase 检查 Referer 头,如果来源符合预期,就设置一个环境变量(比如 allow_access);然后在 FilesMatchLocation 容器中,通过 Require 指令判断该环境变量是否存在,不存在则拒绝访问。下面是一个典型配置:

SetEnvIfNoCase Referer "^http(s)?://(www.)?yourdomain.com" local_referer
SetEnvIfNoCase Referer "^$" allow_blank
# 如果需要允许某些搜索引擎
SetEnvIfNoCase Referer "google.com" search_engine
SetEnvIfNoCase Referer "bing.com" search_engine
<FilesMatch ".(jpg|jpeg|png|gif|svg|webp)$">
    Require env local_referer
    Require env allow_blank
    Require env search_engine
</FilesMatch>

这段配置创建了三个环境变量:local_referer 在 Referer 匹配本站域名时设置,allow_blank 在 Referer 为空时设置,search_engine 在 Referer 中包含 google.com 或 bing.com 时设置。在 <FilesMatch> 块中,Require env 语句之间是“或”的关系,即只要上述三个环境变量任意一个被设置,请求就会被允许;否则返回 403。这种方式比 mod_rewrite 更直观,排查问题时也更容易看清哪个条件被满足。

需要注意的是,Apache 2.4 以上版本才支持 Require env 的多条件或逻辑。如果还在使用 2.2 版本,则需要借助 OrderDeny 指令配合 Satisfy any,但这种方式配置较为繁琐,建议升级。此外,SetEnvIf 的所有条件检查同样基于 Referer 头,因此也同样面临 Referer 被屏蔽的问题,必须对空白 Referer 做出明确处理,否则用户直接访问图片会被 403 拦截。

实战:兼顾空白 Referer、搜索引擎与直接访问的完整配置

结合前面两种方案的优点,我们可以构建一个既能拦截恶意盗链,又能友好对待正常用户和搜索引擎的配置。这里以 mod_rewrite 为例,因为它更灵活,能处理更复杂的需求。

首先,需要明确允许的列表:你自己的域名及其子域名、可能使用的 CDN 域名、主流搜索引擎的 Referer,以及空白 Referer。对于 CDN,如果你使用了阿里云 OSS 或 CloudFlare,通常请求通过 CDN 回源时,Referer 可能是 CDN 自身的域名,需要将其加入白名单。搜索引擎不仅包括 Google、Bing,还有百度、搜狗等,你可以根据实际访问日志来补齐。

RewriteEngine on

# 定义允许的域名和特殊情况
RewriteCond %{HTTP_REFERER} ^$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http(s)?://(www.)?yourdomain.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^http(s)?://(www.)?your-cdn-domain.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^http(s)?://(www.)?google. [NC,OR]
RewriteCond %{HTTP_REFERER} ^http(s)?://(www.)?bing. [NC,OR]
RewriteCond %{HTTP_REFERER} ^http(s)?://(www.)?baidu. [NC,OR]
RewriteCond %{HTTP_REFERER} ^http(s)?://(www.)?sogou. [NC]

# 如果以上条件都不满足,则禁止访问特定类型的文件
RewriteRule .(jpg|jpeg|png|gif|svg|webp|mp4|zip)$ - [F,L]

注意这里第一条 RewriteCond 后面的 [NC,OR] 标志非常关键:OR 使得多个 Cond 之间形成“或”逻辑,只要其中一条匹配,就不会触发最终的 RewriteRule。也就是说,只要 Referer 为空、来自你的域名、来自 CDN 或来自搜索引擎中的任意一个,请求都会被放行。最后一条 Cond 不加 OR,是为了结束这一组条件的串联。如果所有条件都不匹配,就会执行 RewriteRule 并返回 403。

对于空白 Referer 的放行,建议还是保留。虽然在极端情况下有绕过防盗链的可能(例如某些工具可以伪造空 Referer 发送请求),但对于绝大多数正常用户来说,这是保证可用性的必要妥协。如果你的资源极为敏感,也可以去掉空 Referer 的放行规则,但需要评估对用户体验和搜索引擎抓取的影响。此外,还可以结合 SetEnvIf 或其他手段记录日志,当发现异常流量时再做精准封禁。

测试配置是否正确,可以使用 curl 命令行工具模拟各种场景:

# 模拟没有 Referer 的请求(应该正常返回 200)
curl -I https://yourdomain.com/images/test.jpg

# 模拟来自白名单域名的请求(200)
curl -I -e "https://www.yourdomain.com/page" https://yourdomain.com/images/test.jpg

# 模拟外部盗链请求(应当返回 403)
curl -I -e "https://www.bad-site.com" https://yourdomain.com/images/test.jpg

通过观察 HTTP 状态码,可以快速验证规则是否按预期工作。配置完成后,建议持续关注访问日志,如果发现某些合法来源(如社交媒体、第三方工具)的 Referer 被误拦,将其逐一加入白名单即可。

Apache热链接保护防盗链修改时间:2026-08-12 07:42:57

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。