一、背景
根据用户的IP地址所在地理位置的不同,为用户提供差异化页面内容是一种常见的个性化策略,常用于实现地域定向、或提升用户体验等需求。为了实现这一功能,网站开发者通常会利用服务器端编程语言来检测访问者的地理位置,并据此展示相应的内容或重定向到特定的页面地址。
以下是一个简化的示例流程,说明如何在服务器端实现这一功能:
1、根据IP位置不同,返回不同的页面地址
南京地区,返回静态页面
其他地区,返回动态页面
2、指定如下user_agent 返回动态页面-(主要针对爬虫)
“xb-ios”,
“mgo-ios”,
“Baiduspider”,
“Googlebot”,
“yahoo”,
“YoudaoBot”,
“Sogou”,
“360Spider”,
“Sosospider”,
“YisouSpider”,
“msnbot”,
“bingbot”
3、 指定 如下IP地址,返回动态页面
“117.89.53.221”
“58.240.35.202”
二、openresty服务和模块安装
1、简介
OpenResty 是一个基于 Nginx 的平台和开发框架,它集成了 LuaJIT 和许多 Lua 库,使得开发者能够使用 Lua 语言编写 Nginx 模块,从而构建高性能的 Web 应用和微服务。
lua-resty-http 是一个 Lua 库,它为 OpenResty 提供了 HTTP 客户端功能,允许你在 Nginx 配置中或 Lua 脚本中发出 HTTP 请求。
2、安装
2.1、默认是已经安装好openresty服务(没有安装的小伙伴,可以直接去官网下载安装~)
官方地址:https://openresty.org/cn/download.html
2.2、lua-resty-http模块安装,后续lua脚本需要使用。安装方法如下(选择其中的一个)
- 方法一、lua-resty-http yum安装
yum install perl-Digest-MD5
/usr/local/openresty/bin/opm get pintsized/lua-resty-http
- 方法二、lua-resty-http 手动安装
wget https://github.com/pintsized/lua-resty-http/archive/master.zip
unzip master.zip
sudo cp -r lua-resty-http-master/lib/resty /usr/local/openresty/lualib/
三、获取IP地址库
完成openresty及其所需功能模块的配置后,接下来便是集成IP地址库以实现IP地址解析功能。当前市场上充斥着多种IP数据库选项,为开发者提供了广阔的选择空间。在作出决定时,重要的是要考量应用场景的具体需求、地理定位的精确度、查询速度以及预算限制等多个维度。
1、开源IP地址库:如MaxMind提供的GeoLite2是一个非常流行且免费的IP地理位置数据库。GeoLite2虽然在某些情况下可能不如商业产品精确,但对于多数一般需求来说已经足够。开发者可以通过定期检查或订阅更新通知来保持数据库的时效性。
2、付费IP地址纯真库:对于那些对数据准确性、实时性和全面性有高要求的应用场景,如金融、广告投放、网络安全监控等,建议选择更专业的付费IP地址库。这些服务通常承诺更高的查询速度、更低的延迟、更高的准确率以及更频繁的数据更新。
四、Nginx 配置文件
lua_package_path '/usr/local/openresty/lualib/?.lua;;';
resolver 114.114.114.114;
upstream www.opseye.com {
server 120.55.52.63:80 max_fails=1 fail_timeout=5s;
}
server {
listen 80;
server_name www.opseye.com opseye.com;
access_log /data/logs/1.log main;
error_log /data/logs/1error.log error;
return 301 https://www.opseye.com$request_uri;
}
server {
listen 443 ssl ;
access_log /data/logs/1.log main;
error_log /data/logs/1error.log error;
server_name www.opseye.com opseye.com;
ssl_certificate /usr/local/openresty/nginx/conf/ssl/www.opseye.com.pem;
ssl_certificate_key /usr/local/openresty/nginx/conf/ssl/www.opseye.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location /lua {
default_type text/html;
content_by_lua_block {
local args = ngx.req.get_uri_args()
local ip = ngx.var.remote_addr
local name = args.name or "World"
ngx.say(ip .. "hello" .. name .. "!")
}
}
location / {
default_type 'text/html';
content_by_lua_block {
local http = require "resty.http"
local httpc = http.new()
local ip = ngx.var.remote_addr
local user_agent = ngx.var.http_user_agent
-- 定义需要重定向的 User-Agent 和 IP 地址
local user_agents_to_redirect = {
"xb-ios",
"mgo-ios",
"Baiduspider",
"Googlebot",
"yahoo",
"YoudaoBot",
"Sogou",
"360Spider",
"Sosospider",
"YisouSpider",
"msnbot",
"bingbot"
}
local ips_to_redirect = {
"117.89.53.221",
"58.240.35.202"
}
-- 检查 User-Agent
for _, agent in ipairs(user_agents_to_redirect) do
if user_agent and user_agent:find(agent) then
ngx.exec("@dynamic_city")
return
end
end
-- 检查 IP 地址
for _, redirect_ip in ipairs(ips_to_redirect) do
if ip == redirect_ip then
ngx.exec("@dynamic_city")
return
end
end
local url = "https://c2ba.api.huachen.cn/ip?ip=" .. ip
local res, err = httpc:request_uri(url, {
method = "GET",
headers = {
["Authorization"] = "APPCODE aafabb"
},
ssl_verify = false,
timeout = 5000,
ca_cert_path = "/etc/pki/tls/certs/ca-bundle.trust.crt"
})
if not res then
ngx.say("failed to request: ", err)
return
end
-- 解析返回的JSON数据
local cjson = require "cjson"
local data = cjson.decode(res.body)
if data.ret == 200 then
local city = data.data.city
-- 根据城市重定向
if city == "南京" then
-- ngx.exec('@dynamic_city')
ngx.exec("@nj_static")
else
ngx.exec('@dynamic_city')
end
else
ngx.say("Error in API response")
end
}
}
location @nj_static {
root /data/web/opseye.com;
index index.html index.htm;
}
location @dynamic_city{
add_header backend $upstream_addr;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_ignore_client_abort on;
client_max_body_size 100m;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_pass http://www.opseye.com;
}
}
五、测试
为了验证效果,我们特意选取了来自两个地域的IP地址对目标网址进行访问:一个是位于南京的IP,其得到的是一个静态网页;而所有其他地区的IP访问时,则收到了动态页面的内容。此外,当使用指定爬虫或特定IP地址进行请求时,系统同样呈现了动态页面,确保了测试的全面性与准确性。
-
南京区域,返回静态页面:
-
其他区域,返回动态页面