一、为什么需要基于地理位置的访问控制

想象一下,你运营着一个全球性的网站,但某些地区的用户总是恶意刷接口,或者你需要给特定国家提供定制化内容。这时候,如果能根据用户IP自动识别地理位置并实施访问控制,问题就迎刃而解了。Nginx的geo模块正是为此而生,它像是个智能门卫,能根据IP地址库快速判断访客来源,并执行相应规则。

典型场景

  • 限制特定国家/地区访问(比如合规性要求)
  • 针对不同区域展示不同维护页面
  • 防御地理特征明显的DDoS攻击

二、geo模块的工作原理

Nginx的geo模块通过IP地址匹配规则工作,其核心是创建一个变量,将IP地址映射为特定值。这个映射关系可以来自内置的IP库,也可以自定义。有趣的是,它支持CIDR格式(比如192.168.1.0/24)和范围匹配,甚至能通过default关键字设置兜底值。

技术栈:本文所有示例基于Nginx 1.18+,无需额外安装模块。

# 示例1:基础geo配置
geo $geo_region {
    default         unknown;
    192.168.1.0/24  internal;
    10.0.0.0/8      internal;
    203.0.113.1     cn;
    198.51.100.0/24 us;
}

server {
    listen 80;
    if ($geo_region = "cn") {
        return 403 "区域限制";
    }
    # 其他配置...
}

注释说明

  • $geo_region是自定义变量
  • internal标记内网IP
  • 精确IP和CIDR可混合使用

三、高级应用实战

3.1 结合GeoIP数据库

虽然Nginx自带基础IP识别,但更精准的地理定位需要MaxMind等数据库。以下是整合示例:

# 示例2:加载GeoIP数据库
http {
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    geoip_city    /usr/share/GeoIP/GeoLiteCity.dat;

    map $geoip_country_code $allowed_country {
        default no;
        US      yes;
        JP      yes;
    }
}

server {
    if ($allowed_country = "no") {
        return 302 https://example.com/blocked;
    }
}

关键点

  • geoip_country_code是GeoIP模块提供的变量
  • map指令将国家代码转换为布尔值

3.2 动态黑白名单

通过include指令实现动态加载规则文件:

# 示例3:动态加载规则
geo $blocked_ip {
    include /etc/nginx/conf.d/ip-blocklist.conf;
    default 0;
}

# ip-blocklist.conf内容示例:
# 203.0.113.22 1;
# 198.51.100.0/24 1;

运维技巧

  • 修改ip-blocklist.conf后执行nginx -s reload生效
  • 可配合CI/CD自动更新规则

四、避坑指南与性能优化

4.1 常见问题

  1. CIDR冲突:规则按从上到下匹配,越具体的规则应该越靠前
  2. IPv6支持:需显式启用geoip6数据库
  3. 变量作用域geo定义在http块,但可在server/location使用

4.2 性能优化

  • 使用geo+map替代大量if判断
  • 对高频访问IP采用缓存(如结合$binary_remote_addr
  • 大型IP库建议改用OpenResty的lua-resty-iputils
# 示例4:高效缓存实现
geo $remote_addr $ratelimit_key {
    default         0;
    192.168.1.100   1;
}

limit_req_zone $ratelimit_key zone=api_limit:10m rate=10r/s;

五、技术对比与替代方案

5.1 与其他方案对比

方案 精度 性能影响 维护成本
Nginx geo
Cloudflare GEO
自建IP库API

5.2 何时选择geo模块

  • 需要快速实现基础地域封锁
  • 已有Nginx基础设施不愿引入新组件
  • 对地理位置精度要求不高(城市级即可)

六、总结

Nginx的geo模块就像瑞士军刀中的小镊子——看似不起眼,但在特定场景下能解决大问题。虽然它不如专业GeoIP服务精确,但其零额外依赖、高性能的特性,使其成为轻量级地理位置控制的绝佳选择。下次遇到"这个IP段要特殊处理"的需求时,不妨先试试这个小而美的功能模块。