地域分流依赖CDN透传地理头(如CF-IPCountry),Nginx通过map指令映射并proxy_pass至对应upstream;需确保CDN开启地域头传递且不参与缓存键,配置须在http块顶层,验证时检查请求头与日志输出。

理解地域分流的核心逻辑
地域分流不是靠 Nginx 自身识别用户地理位置,而是依赖 CDN 提供的请求头(如 X-Forwarded-For、CF-IPCountry(Cloudflare)、X-Country-Code(阿里云全站加速)、True-Client-IP 等)传递客户端真实国家或区域信息。Nginx 在接收到这些头部后,通过 map 指令做映射判断,再结合 if 或 try_files 控制 upstream 选择或响应内容。
CDN 端需开启并透传地域标识头
不同 CDN 厂商配置方式不同,但关键点一致:
- Cloudflare:默认透传 CF-IPCountry(值为 ISO 3166-1 alpha-2 国家码,如 CN、US、JP),无需额外开启;若用 WAF 或自定义规则,需确认未覆盖该头
- 阿里云 CDN / 全站加速:在「HTTP 头管理」中启用「传递客户端国家/省份/城市信息」,会注入 X-Country-Code、X-Province-Code 等
- 腾讯云 CDN:在「访问控制 > 地域访问控制」开启后,可通过 QC-Region 或 QC-Country 获取(具体以控制台文档为准)
- 务必在 CDN 缓存规则中设置「忽略地域头不参与缓存键」,避免因头字段导致缓存污染(例如:将 CF-IPCountry 加入 cache key 会导致同一 URL 被缓存多份)
Nginx 配置地域分流的实际写法
以下以 Cloudflare 为例,实现「中国用户走国内源站,海外用户走香港源站」的典型场景:
在 http 块中定义地域映射:
map $http_cf_ipcountry $backend {
default "hk_upstream";
CN "cn_upstream";
HK "cn_upstream";
TW "cn_upstream";
MO "cn_upstream";
}
定义两个 upstream(可指向不同 IP、域名或服务发现地址):
upstream cn_upstream {
server 192.168.1.10:8080; # 国内源站
keepalive 32;
}
<p>upstream hk_upstream {
server 192.168.2.20:8080; # 香港源站
keepalive 32;
}</p>
在 server 块中应用分流逻辑:
server {
listen 80;
server_name example.com;
<pre class="brush:php;toolbar:false;">location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 根据 map 结果选择 upstream
proxy_pass http://$backend;
# 可选:记录实际路由到的区域,便于日志分析
log_by_lua_block {
ngx.var.log_region = ngx.var.backend;
}
}
}
注意:map 指令必须在 http 块顶层定义,不能放在 server 或 location 内;$http_XXX 是自动从请求头转成的小写下划线变量名(如 CF-IPCountry → $http_cf_ipcountry)。
验证与排错要点
地域分流容易出问题的环节集中在「头是否真能拿到」和「值是否符合预期」:
- 用 curl 模拟请求验证 CDN 是否透传:
curl -H "CF-IPCountry: US" https://example.com -I(本地测试时可手动加头) - 在 Nginx access_log 中临时加入 $http_cf_ipcountry 和 $backend 字段,确认日志输出是否匹配预期
- 检查 CDN 是否开启了「IP 回源」或「强制 HTTPS」,避免因协议/头被清洗导致地域头丢失
- 若使用了 WAF 或边缘脚本(如 Cloudflare Workers),确保它们没有删除或改写地域相关 header
- 浏览器开发者工具 Network 标签页查看 Response Headers,确认 CDN 返回的 Server 或 Via 字段是否表明请求确实经过 CDN










