如何通过Nginx配置仅允许Reddit热链图片并实现访问跳转
Reddit自有图片热链控制实现方案
原有配置失效原因
valid_referers规则中加入了none参数,所有不带Referer的请求(含用户直接在地址栏输入图片地址的请求)会被判定为合法来源,直接返回原图,无法触发跳转- 仅通过Referer字段无法区分两类同属Reddit来源的请求:帖子页内嵌加载图片资源、用户点击图片触发的页面导航请求,两类请求的Referer都可能携带Reddit域名,原有规则会统一放行,无法触发跳转
- 未利用浏览器请求的标准
Accept头做场景区分,这是实现类Tumblr热链跳转机制的核心判断依据
核心判断逻辑
两类请求的浏览器请求头存在明确差异,可以精准区分:
- Reddit页面内嵌加载图片时:
<img>标签发起的资源请求,Accept头最高优先级为图片类型,不会以text/html开头 - 用户点击图片跳转/直接访问图片地址时:属于浏览器页面导航场景,
Accept头最高优先级为网页类型,固定以text/html开头 - 非Reddit来源的盗链请求、无Referer的直接访问请求,全部判定为需要跳转的场景
可用Nginx配置
location ~* ^/(?<filenum>.*)\.(jpeg|jpg|png|webp|gif)$ { set $is_reddit_embed 0; # 匹配所有Reddit官方域名的Referer if ($http_referer ~* "https?://([a-z0-9-]+\.)?reddit\.(com|it)/") { set $is_reddit_embed 1; } # 匹配Reddit短链域名redd.it的Referer if ($http_referer ~* "https?://([a-z0-9-]+\.)?redd\.it/") { set $is_reddit_embed 1; } # Reddit来源的内嵌图片加载请求,正常返回源站图片 if ($is_reddit_embed = 1) { if ($http_accept !~* "^text/html") { add_header Cache-Control "public, max-age=86400"; proxy_pass http://195.xxx.xxx.xxx:7492; break; } } # 其余所有场景统一301跳转到站点对应内容页 add_header Cache-Control "no-cache, no-store, must-revalidate"; return 301 https://example.com/$filenum; }
配置说明
- 移除原有
valid_referers相关规则,不要在白名单中加入none、blocked参数,避免漏判直接访问的请求 - 缓存规则区分设置:内嵌图片可设置1天缓存降低源站压力,跳转响应强制不缓存,避免跳转规则被浏览器或CDN缓存导致异常
- 配置生效前需要清空Nginx缓存、本地浏览器缓存测试,旧的301响应缓存会影响规则验证
- 如果需要兼容其他平台的热链展示,只需要新增对应平台的Referer匹配规则即可,保留
Accept头的判断逻辑就能实现“平台内嵌显示、点击跳转到自有站点”的效果
内容的提问来源于stack exchange,提问作者TravelWhere
相关产品推荐
相关产品推荐

