当referer白名单为空时,可通过map模块结合ip、user-agent等客户端特征放行特定请求:先判断referer是否合法,再对空referer请求校验可信ip或ua,最终or合并结果控制访问。

当 Nginx 的 Referer 限制中,白名单域名为空(即未配置合法来源)时,仍需允许特定客户端(如内部监控工具、本地调试请求、或固定 IP 的爬虫)直接抓取资源,可以通过 map 模块结合客户端特征(如 IP、User-Agent、Header)灵活控制访问逻辑,而不是单纯依赖 Referer。
利用 map 匹配空 Referer + 客户端特征放行
map 模块支持对多个变量做复合判断。关键思路是:当 $http_referer 为空(或非法)时,不直接拒绝,而是转入二次校验——检查是否来自可信 IP 或携带特定标识。
- 定义一个
$allowed_by_client变量,综合判断:$http_referer是否为空、$remote_addr是否在内网/白名单、或$http_user_agent是否匹配预设值 - 用嵌套
map或单层map的多条件表达式(借助正则与字符串匹配)实现逻辑组合 - 最终将
$allowed_by_client与原有 Referer 白名单结果(如$valid_referer)做 OR 运算,作为最终放行依据
配置示例:空 Referer 下按 IP 和 UA 放行
以下配置允许:① 正常 Referer 来源;② Referer 为空但来自 10.0.0.0/8 或 UA 含 curl-monitor 的请求:
map $http_referer $valid_referer {
~^(https?://(example\.com|api\.company\.org)(:[0-9]+)?/?)$ 1;
default 0;
}
<p>map $http_referer $allowed_empty_referer {
"" 1; # 空 Referer 触发后续判断
default 0;
}</p><p>map $allowed_empty_referer $by_client {
0 0; # 非空 Referer,跳过客户端校验
1 $remote_addr; # 空 Referer 时,把 IP 当作 key 传入下一层 map
}</p><h1>根据 IP 或 UA 决定是否放行(空 Referer 场景)</h1><p>map $by_client $client_trusted {
~^10.0.0. 1; # 内网 IP
~^127.0.0.1$ 1;
default $http_user_agent;
}</p><p>map $client_trusted $final_allow {
1 1;
~curl-monitor 1; # UA 包含 curl-monitor 即放行
default 0;
}</p><h1>最终判断:Referer 合法 或 客户端可信</h1><p>map $valid_referer$final_allow $allowed {
~^1 1; # 只要任一为 1(字符串拼接后以 1 开头),即放行
default 0;
}</p>
然后在 server 或 location 中使用:if ($allowed = 0) { return 403; }
更简洁的写法:用 map 直接合并判断逻辑
避免多层 map 嵌套,可将所有条件压缩到一个 map 中(Nginx 1.11.6+ 支持在 map 中使用多个变量):
map "$http_referer:$remote_addr:$http_user_agent" $access_granted {
~^https?://(example\.com|api\.company\.org):.* 1; # 正常 Referer
~^:$10\.0\.0\.[0-9]+:.* 1; # 空 Referer + 内网 IP
~^:127\.0\.0\.1:.* 1;
~^::curl-monitor$ 1; # 空 Referer + 特定 UA
default 0;
}
注意:"$http_referer:$remote_addr:$http_user_agent" 是拼接键,用冒号分隔。正则中 ^: 表示 Referer 为空(开头是冒号),:: 表示 Referer 和 IP 都为空(极少,但可覆盖本地 curl 测试场景)。
注意事项与避坑点
map 在 nginx.conf 的 http 块中定义,不能放在 server 内;变量名不能重复;空 Referer 的判定要区分真实空值("")和缺失(undefined),实际中两者都映射为 "",所以用 "" 匹配即可。
- 测试空 Referer 请求时,用
curl -H "Referer:" ...或curl -H "Referer:" --referer "" ...,避免被浏览器自动补全 - 若需支持 HTTPS 下的 Referer 跳转丢失(如从 HTTPS 到 HTTP),需额外考虑协议降级场景,此时 Referer 可能被浏览器清空,应归入“空 Referer”分支统一处理
- 不建议仅靠 User-Agent 防御——易伪造;生产环境应优先结合 IP、Token Header(如
X-Internal-Token)等更可靠标识











