在使用Cloudflare CDN时,CDN传给后端服务器中只传递了有限的 http request hearder。
其中只包含了非常简陋的 ip 信息,例如只有 CF-IPCountry ,不足以实现一个查询ip信息的api,要想实现查询ip详细信息需要借助 Cloudflare Workers 来实现。
Cloudflare Workers 传入的 HTTP 请求都被称为 fetch 事件,fetch 事件中都包含一个 Request 接口实例,在这个 Request 实例中就包括了访问 ip 的详细信息
通过访问 Request.cf 可以获得 Cloudflare 提供的请求信息,包含了 ip 的详细信息;访问 Request.headers 则可以获得访客的 HTTP headers,写一个简单的 Workers 处理一下 Request.cf 、Request.headers 中的信息,并返回 Json 格式即可。
访问该 Cloudflare Workers 后返回包含访客 IP、Continent、Country、Region、ASN 等 ip 信息及请求的Header信息,同时也会把 Cloudflare 的 https 连接信息及 bot 识别的相关信息一起返回。
代码如下:
export default {
async fetch(request) {
const data = {
Method: request.method,
Url: request.url,
IP: {
IP: request.headers.get('CF-Connecting-IP'),
Continent: request.cf.continent,
Country: request.cf.country,
IsEU: request.cf.isEUCountry,
Region: request.cf.region,
RegionCode: request.cf.regionCode,
City: request.cf.city,
Latitude: request.cf.latitude,
Longitude: request.cf.longitude,
PostalCode: request.cf.postalCode,
MetroCode: request.cf.metroCode,
Colo: request.cf.colo,
ASN: request.cf.asn,
ASOrganization: request.cf.asOrganization,
Timezone: request.cf.timezone
},
Headers: {},
Security: {}
};
// 遍历并存储每个 HTTP 头,排除以 cf- 开头的 HTTP 头
request.headers.forEach((value, name) => {
if (!name.toLowerCase().startsWith('cf-')) {
data.Headers[name] = value;
}
});
// 遍历 request.cf 并存储所需对象的属性到 Security 中
for (const key in request.cf) {
if (
key == 'clientTcpRtt'
|| key == 'tlsCipher'
|| key == 'tlsVersion'
|| key == 'httpProtocol'
|| key == 'clientHandshake'
|| key == 'clientFinished'
|| key == 'serverHandshake'
|| key == 'serverFinished'
|| key == 'corporateProxy'
|| key == 'verifiedBot'
|| key == 'score'
) {
if (typeof request.cf[key] === 'object') {
for (const innerKey in request.cf[key]) {
data.Security[innerKey] = request.cf[key][innerKey];
}
} else {
data.Security[key] = request.cf[key];
}
}
}
var dataJson = JSON.stringify(data, null, 4);
console.log(dataJson);
return new Response(dataJson, {
headers: {
"Content-Type": "application/json;charset=UTF-8"
}
})
}
};
需要注意 Cloudflare Workers 的域名被屏蔽了,建议绑定一个域名来访问。请求该 Workers 后返回如下 JSON :
{
"Method": "GET",
"Url": "https://ip.ipip.dev/",
"IP": {
"IP": "149.234.194.181",
"Continent": "NA",
"Country": "US",
"Region": "Missouri",
"RegionCode": "MO",
"Latitude": "38.57740",
"Longitude": "-90.67090",
"Colo": "IAD",
"ASN": 23167,
"ASOrganization": "Bayer-arch",
"Timezone": "America/Chicago"
},
"Headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-encoding": "gzip",
"accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7",
"connection": "Keep-Alive",
"host": "ip.ipip.dev",
"sec-ch-ua": "\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
"x-forwarded-proto": "https",
"x-real-ip": "149.234.194.181"
},
"Security": {
"clientTcpRtt": 1,
"tlsCipher": "AEAD-AES128-GCM-SHA256",
"tlsVersion": "TLSv1.3",
"httpProtocol": "HTTP/2"
}
}