在使用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"
    }
}