mod_setenvif无法直接识别地理位置,必须先由mod_maxminddb等模块解析IP并注入GEOIP_COUNTRY_CODE等环境变量,再用SetEnvIf基于ISO码条件设变量如is_china_region,最后在日志、访问控制或响应头中显式调用。

mod_setenvif 本身不能直接识别地理位置。它只负责“匹配已有字段并设变量”,不提供 IP 地理查询能力。要实现基于地理位置的动态变量定义,必须分两步走:先由其他模块(如 mod_maxminddb)把 IP 解析成国家/地区码并注入环境变量;再用 SetEnvIf 对这些地理变量做条件判断和标记。
必须前置地理信息注入
原始请求里只有 Remote_Addr(如 203.123.45.67),没有 CountryCode 这类字段。Apache 默认不查 GeoIP 数据库,所以不能靠 SetEnvIf 直接写 “如果 IP 属于中国就设 GEO_CN=1”。你得先让 mod_maxminddb 或 mod_geoip2 在请求早期完成解析,并把结果存为环境变量,比如 GEOIP_COUNTRY_CODE=CN。
- 推荐使用 mod_maxminddb(基于 MaxMind GeoLite2):加载后配置数据库路径和映射关系,例如
MaxMindDBEnable On
MaxMindDBFile GEOIP_COUNTRY_DB /usr/share/GeoIP/GeoLite2-Country.mmdb
MaxMindDBEnv GEOIP_COUNTRY_CODE COUNTRY_ISO_CODE
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 确保该模块已启用(a2enmod maxminddb),且数据库文件可读
用 SetEnvIf 对地理变量做条件标记
一旦 GEOIP_COUNTRY_CODE 可用,就可以用 SetEnvIf 按 ISO 国家码批量打标签。注意大小写敏感、正则写法和变量命名规范:
- 匹配中国大陆、香港、台湾:SetEnvIf GEOIP_COUNTRY_CODE ^(CN|HK|TW) is_china_region
- 匹配美国和加拿大:SetEnvIf GEOIP_COUNTRY_CODE ^(US|CA) is_north_america
- 变量名避免连字符,推荐下划线;值设为 1 更利于布尔判断
- 这些指令需放在 VirtualHost 或主配置中,.htaccess 通常不可用(需 AllowOverride FileInfo 且权限允许)
后续如何使用这些地理变量
设好的 is_china_region 这类变量不会自动生效,必须显式调用才能起作用:
- 日志分流:CustomLog logs/access_cn.log combined env=is_china_region
- 访问控制:<RequireAll><Require env is_china_region></RequireAll>
- 响应头标记:Header set X-Geo-Region %{is_china_region}e env=is_china_region
- PHP 中可通过 $_SERVER['is_china_region'] 获取(注意内部重定向时可能加 REDIRECT_ 前缀)
常见误区与注意事项
有人试图用 Remote_Addr 直接匹配国内段 IP,这既不可靠也不可持续——IP 归属地会变,CIDR 段难穷举,且 CDN 或代理会让 Remote_Addr 失真。真正有效的地理判断必须依赖权威数据库解析。另外,SetEnvIf 不支持后向引用($1)、不能在子请求(如目录索引)中继承变量、正则中反斜杠需加倍转义(如匹配点号要写 \.)。

















