背景

根据用户 IP 地址所在位置,为用户提供差异化页面内容是常见的个性化策略,广泛用于地域定向、内容本地化或用户体验优化场景。网站开发者通常利用服务器端技术检测访问者地理位置,并展示相应内容或重定向页面。

本文实现的路由逻辑:

  1. 根据 IP 所在位置返回不同页面地址
    • 南京地区 → 返回静态页面
    • 其他地区 → 返回动态页面
  2. 指定特定 User-Agent(如爬虫)→ 返回动态页面
  3. 指定特定 IP 地址 → 返回动态页面

OpenResty 简介

OpenResty 是基于 Nginx 的高性能 Web 平台,集成了 LuaJIT 和丰富的 Lua 库,支持开发者使用 Lua 脚本编写 Nginx 模块,构建高性能 Web 应用和 API 网关。

lua-resty-http 是为 OpenResty 提供 HTTP 客户端功能的第三方库,可在 Lua 脚本中发起 HTTP 请求。

安装 OpenResty 与依赖模块

方法一:通过 yum 安装依赖

yum install perl-Digest-MD5
yum install openresty

方法二:手动安装 lua-resty-http

wget https://github.com/pintsized/lua-resty-http/archive/master.zip
unzip master.zip
cp lua-resty-http-master/lib/resty/http*.lua /usr/local/openresty/lualib/resty/

获取 IP 地址库

实现地域定向需要 IP 地理位置数据库,市场上主要有两类选择:

  • 开源方案:MaxMind 的 GeoLite2(免费,但精确度可能低于商业产品,适合一般场景)
  • 付费方案:适合对精确性要求高的场景,如金融、广告投放、安全监控等

下载 GeoLite2 或商业 IP 库后,解压到指定目录(如 /usr/local/share/GeoIP/)。

Nginx 配置

nginx.conf 或对应 server 配置文件中加入以下内容:

# 指定 Lua 模块搜索路径
lua_package_path '/usr/local/openresty/lualib/?.lua;;';

# 加载 GeoIP2 模块(或使用 lua-resty-maxminddb)
geoip2 /usr/local/share/GeoIP/GeoLite2-City.mmdb {
    auto_reload 60m;
    $geoip2_data_city_name city names zh-CN;
    $geoip2_data_region_name subdivisions 0 names zh-CN;
}

server {
    listen 80;
    server_name example.com;

    location / {
        content_by_lua_block {
            local city = ngx.var.geoip2_data_city_name or ""
            local ua = ngx.var.http_user_agent or ""
            local client_ip = ngx.var.remote_addr

            -- 特定 IP 白名单,强制返回动态页面
            local static_ips = {["1.2.3.4"] = true}

            -- 爬虫 User-Agent 检测
            local is_bot = string.find(ua, "bot", 1, true) or
                           string.find(ua, "spider", 1, true) or
                           string.find(ua, "crawl", 1, true)

            -- 路由判断
            if static_ips[client_ip] or is_bot then
                -- 指定 IP 或爬虫,返回动态页面
                ngx.exec("@dynamic")
            elseif string.find(city, "南京", 1, true) then
                -- 南京地区,返回静态页面
                ngx.exec("@static")
            else
                -- 其他地区,返回动态页面
                ngx.exec("@dynamic")
            end
        }
    }

    location @static {
        root /var/www/static;
        index index.html;
    }

    location @dynamic {
        proxy_pass http://backend_server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

测试结果

配置完成后,验证以下场景是否符合预期:

测试场景预期结果验证方式
南京 IP 访问返回静态页面使用南京 IP 的设备直接访问
非南京 IP 访问返回动态页面使用其他地区 IP 或 VPN 访问
爬虫 User-Agent返回动态页面curl 携带 Googlebot UA 请求
特定 IP 访问返回动态页面使用白名单 IP 访问

测试验证显示:南京区域正确返回静态页面,其他区域正确返回动态页面,指定爬虫 UA 和特定 IP 也按预期返回动态页面,路由逻辑运行正常。

小结

基于 OpenResty 的地域定向方案,利用 Lua 脚本的灵活性,可以在 Nginx 层面实现细粒度的流量路由控制,无需修改后端应用代码。结合 GeoIP 数据库,可快速实现按地区、按 UA、按 IP 的多维度差异化访问策略,是轻量级地域化运营的理想方案。