Creating a Simple IP-Check Tool with Cloudflare Workers

Introduction

In this guide I will show you how to create your first Worker using the dashboard. There is also an option for local development via Wrangler.

Cloudflare Workers can be written in JavaScript or TypeScript. Serverless JavaScript is JavaScript code that comprises all or part of an application, is only run when requested, and is not hosted on proprietary servers.

Learn more about Serverless JavaScript on Cloudflare.com.


Requirements

The only requirement is a free Cloudflare account, but I highly recommend that you have at least one domain registered at Cloudflare.


Limitations

Free accounts are limited to 100,000 requests per day. This should be enough for most use cases.


Creating your first Worker

General Information

When a request to your subdomain or to your Cloudflare-managed domain is received by any of Cloudflare’s runtimes, the Workers script is passed a FetchEvent argument to the event handler defined in the script. From there you can generate a Response by computing a response on the spot, calling to another server using fetch.

Learn more about Workers on Cloudflare.com.

Setup

If not already done you have to define a Worker-Domain. For example myname which will translate to myname.workers.dev. So all your Worker will be registered below your Worker Domain. For example myworker.myname.workers.dev. You can also define custom paths for your Workers, but I will get to that later on.

Navigate to the Workers-Tab on your Cloudflare dashboard and select Create a Service. If you want you can give your Worker a custom Service name. The Worker template doesn’t matter as we will replace it anyway. Click Create service. You can now select Quick edit in your Workers overview.

Script Template/Example

Replace the example code with the following:

async function handleRequest(request) {
  const clientIP = request.headers.get('CF-Connecting-IP');
  return new Response(clientIP + "\n");
}

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

Test the Script

You can now copy and paste your Workers URL in your browser, and it should display your external IP address.

Script Explanation

Cloudflare passes all HTTP request headers to your origin web server and adds additional headers. One of those additional headers is CF-Connecting-IP. On every request the script gets the CF-Connecting-IP attribute and returns it. The request however has to match your Workers route. In the next step we will define a custom route.


Adding Custom Worker Routes

While I’m using a subdomain (ip.niksec.com) you could also use a URL path to trigger your Worker. For example niksec.com/ip. In the following I will explain the basics of Worker routes.

Select your Worker and navigate to the Triggers tab. The default workers.dev route can be disabled. Click Add route and select your Zone.
As a route I will add ip.niksec.com as I only need an exact match. Another exact match example would be nikec.com/ip. Confirm with by clicking Add route.

But you can also use wildcards in Worker routes. I will give you a few examples:

  • *.niksec.com would match:
    • test.niksec.com
    • example.niksec.com
  • niksec.com/* would match:
    • niksec.com/test
    • niksec.com/example

You can also match all requests to a specific domain by using *niksec.com/*.

Keep in mind that if you define multiple route pattern the most specific one wins.
For example the pattern niksec.com/test/* would take precedence over niksec.com/* when matching a request for niksec.com/test/example.


CURL

Just a quick note if you plan to use CURL.
I disabled HTTPS for my Worker subdomain so that I can simply use curl ip.niksec.com instead of curl https://ip.niksec.com. This is not required, but I find it more practical this way.

There are multiple ways to achieve this:

  • disable HTTPS for your whole domain
    • not recommended if you run other services on the same domain
  • disable HTTPS using Page Rules for specific path or subdomain

Disable HTTPS for Domain

Not recommended!
Select your domain and disable HTTPS redirect under SSL/TLS -> Edge Certificates -> Always Use HTTPS.

Cloudflare Page Rule

From your domain overview select Rules -> Pages Rules -> Create Page Rule.
In the URL text box you can either enter your subdomain or URL path as mentioned earlier.
For example ip.niksec.com or niksec.com/ip/.

To disable HTTPS (only if the URL defined above is matched) you can set the action to Disable Security. Apply the settings with Save and Deploy.


Advanced Script

I also created another example script showing more information like ISP, User-Agent and more. This information is also provided by Cloudflare’s headers and request.cf object.

Learn more about Requests on Cloudflare.com.

async function handleRequest(request) {
  const clientUA = request.headers.get('User-Agent');
  const clientIP = request.headers.get('CF-Connecting-IP');
  const clientASN = request.cf.asn;
  const clientISP = request.cf.asOrganization;
  const clientCO = request.cf.country;
  const clientCI = request.cf.city;
  const clientRE = request.cf.region;
  const clientLAT = request.cf.latitude;
  const clientLON = request.cf.longitude;
  const clientPC = request.cf.postalCode;
  const clientTZ = request.cf.timezone;

  return new Response("Public IP: " + clientIP + "\n" + 
  "ASN: " + clientASN + "\n" + 
  "ISP: " + clientISP + "\n" + 
  "Country: " + clientCO + "\n" + 
  "City: " + clientCI + "\n" + 
  "Region: " + clientRE + "\n" + 
  "Latitude, Longitude: " + clientLAT + "," + clientLON + "\n" + 
  "Postal Code: " + clientPC + "\n" + 
  "Timezone: " + clientTZ + "\n" + 
  "User Agent: " + clientUA + "\n"
  );
}

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

Conclusion

You have now created your own IP check tool using only Cloudflare Workers. This is just an easy example, and you can expand this tool with custom HTML, CSS or by adding new values and statistics.