需求背景
- 防止圖片被外部網站盜鏈 (消耗頻寬、版權保護)
- 管理後台 (admin.xxx.com.cn) 需正常顯示圖片 (審核、編輯)
- 特定目錄結構需精確匹配重寫
完整配置方案
location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
# 合法來源:當前站點域名 + 管理後台域名
valid_referers server_names admin.xxx.com.cn;
# 非法來源觸發重寫
if ($invalid_referer) {
# 目錄結構 1:/folderpath1/aa/bb/xxx.jpg
rewrite "^/folderpath1/([a-z0-9]{2})/([a-z0-9]{2})/([0-9a-z]*)\.([a-z0-9]{3})$" /403.html last;
# 目錄結構 2:/folerpath2/aa/bb/xxx.png (注意原文拼寫 folerpath2)
rewrite "^/folerpath2/([a-z0-9]{2})/([a-z0-9]{2})/([0-9a-z]*)\.([a-z0-9]{3})$" /403.html last;
}
# 靜態資源長期快取
expires 365d;
}
關鍵技術點解析
valid_referers 參數詳解
| 參數 | 含義 |
none | 無 Referer 標頭 (直接輸入網址、書籤、HTTPS→HTTP) |
blocked | Referer 被防火牆/代理過濾/修改 (不含完整域名) |
server_names | 當前 server_name 列表中的域名 (關鍵參數,文中強調必須加上) |
*.example.com | 泛域名匹配 |
~regex | 正則匹配 Referer |
正則重寫規則分解
^/folderpath1/([a-z0-9]{2})/([a-z0-9]{2})/([0-9a-z]*)\.([a-z0-9]{3})$
# 路徑固定開頭
# 第1層:2位小寫字母/數字
# 第2層:2位小寫字母/數字
# 檔名:任意長度字母數字
# 副檔名:3位字母數字
# 重寫至 /403.html,last 重新匹配 location
完善版配置 (修正拼寫、擴充副檔名、優化效能)
# 定義防盜鏈區塊 (可 include 復用)
location ~* \.(gif|jpe?g|png|bmp|webp|svg|swf|ico)$ {
valid_referers none blocked server_names admin.example.com cdn.example.com;
if ($invalid_referer) {
# 統一導向防盜鏈圖片或 403
return 403;
# 或 rewrite ^/ /static/images/hotlink.png redirect;
}
expires 365d;
add_header Cache-Control "public, immutable";
# 可選:限制單連線下載速度
# limit_rate 500k;
# limit_rate_after 1m;
}
進階:Map 模組預計算 $invalid_referer (高併發優化)
# http 區塊
map $http_referer $is_invalid_referer {
default 1;
"~*^https?://([^/]+\.)?example\.com" 0;
"~*^https?://([^/]+\.)?admin\.example\.com" 0;
"~*^https?://([^/]+\.)?cdn\.example\.com" 0;
}
server {
location ~* \.(gif|jpe?g|png|webp)$ {
if ($is_invalid_referer) {
return 403;
}
expires 365d;
}
}
驗證測試
# 正常引用 (200)
curl -H "Referer: https://example.com/page.html" -I https://example.com/images/photo.jpg
# 管理後台引用 (200)
curl -H "Referer: https://admin.example.com/edit.html" -I https://example.com/images/photo.jpg
# 外部盜鏈 (403)
curl -H "Referer: https://evil.com/steal.html" -I https://example.com/images/photo.jpg
# 無 Referer (依策略 200/403)
curl -I https://example.com/images/photo.jpg
避坑總結
- valid_referers 必須加 server_names,否則本站域名也會被判定為非法
- 正則路徑匹配需精確對應實際目錄結構,注意大小寫 (Linux 區分大小寫)
if 在 location 中行為詭異,**能用 valid_referers + return 就不用 rewrite**
- 防盜鏈圖片本身**不能**觸發防盜鏈,需放行或放在單獨 location
- HTTPS 站點引用 HTTP 資源瀏覽器不發送 Referer,需配合
Referrer-Policy 標頭