Posted on

Cloudflare Domain Proxy with port targets?

Scenario(s): 

You have one or more of the following problems to solve;

  • You are an iGaming provider, that needs quickly interchangeable domains in countries like Indonesia to work.
  • You need an additional domain to hit your existing HTTPS target, but can’t run multiple SSL certs.
  • You need to map a call to a direct port on the target, yet, still use CF functionality without the need for custom ports?
  • You want cheaper SSL termination for a whole host of endpoint domains leading to a single target?
  • any other similar case or need.

You need:

  • An easily configurable Cloudflare worker domain proxy.
  • A worker path setup on the domain.

Here is the step by step solution to the problem:

1) Create the CF worker and name it. 

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

async function handleRequest(request) {
    // Define the subdomain to port and domain mapping
    const subdomainPorts = {
        'script-name':   { port: '443',  domain: 'realtarget.com' },
        'subdomain1':    { port: '443',  domain: 'realtarget.com' },
        'subdomain2':    { port: '1201', domain: 'realtarget.com' },
         ...
        'subdomain9':   { port: '1209', domain: 'realtarget.com' },
    };

    // Get the URL of the incoming request
    const url = new URL(request.url);
    url.protocol = 'https:' ; // Ensure HTTPS on target.
    url.port = '443'; // Default to standard HTTPS port if not found

    // Break the hostname into parts
    const hostnameParts = url.hostname.split('.');

    // Assume the first part of the hostname is the first subdomain
    let firstSubdomain = hostnameParts[0];

    // Check if the first subdomain is in the subdomainPorts mapping
    if (firstSubdomain in subdomainPorts) {
        // Construct new hostname using the first subdomain and target domain
        url.hostname = `${firstSubdomain}.${subdomainPorts[firstSubdomain].domain}`;
        url.port = subdomainPorts[firstSubdomain].port;
    } else {
        // Handle cases where subdomain is not defined in the mapping - default domain or handle as needed
        url.hostname = firstSubdomain + '.realtarget.com'; // Default domain if subdomain is not found
    }

    // Disable the line if you don't want logging. 
    console.log(JSON.stringify(url)) ;

    // Create a new request by cloning the original request to preserve all headers, method, body, etc.
    const newRequest = new Request(url, request);
    // Fetch the response from the new URL
    const response = await fetch(newRequest);
    // Return the response to the client
    return response;
}

2) On the domain DNS settings:

  • Make sure the domain (realtarget.com) itself has a A record going somewhere.
  • Add a CNAME for each of the subdomains, pointing to the domain target.
    Ie:  subdomain1 IN CNAME realtarget.com

3) Caching for targets:

Under “Caching” –> “Configuration”,  Set the caching level to “Standard”.

4) Setting up the worker path:

Under “Workers Routes”, click create “Add route”
and enter *.<newdomain.com>/* as the capture path, and select your worker to handle it.

Done!

What will happen next when you use your new shiny domain “foo.com”, is:

The client types in the new shiny domain https://subdomain1.foo.com/path?args…

  1. The script will strip off everything after the first subdomain (subdomain1).
  2. It will replace the domain with realtarget.com, and map the port to 1201, effectively making
    https://subdomain1.foo.com/path?args… appear as:
    https://subdomain1.realtarget.com:1201/path?args… keeping all the headers, body, arguments and whatnot as is, making both client and the final target happy,
    and you only need a single certificate for the target host, that can even be a long-life self-signed certificate,
    using the CF as the certificate front.

 

or, in a picture (a drawio diagram).

Enjoy!

 

Posted on

GPS Location?

Need a routine to determine if a lat/long is inside or outside a specific area?

Here’s a Golang routine for this, that can be easily adopted to any other language.

/*
 * Free to use as you see fit. 
 */

package GPS

type polygon [][]float64

// Enter the lat,long coordinates (min 3)
// poly := [][]float64{ { 1,1 }, { 1,2 }, { 2,2 }, { 2,1 } ... {1,1}}
// Make sure the polygon coordinates are specified in the correct order,
// typically in a counter-clockwise direction, and that the last vertex is
// the same as the first one to close the polygon.
// in := inside(1.5, 1.5, poly) --> True
// in := inside(2.5, 1.5, poly) --> False

// Test if a GPS coordinate is inside the bounding box
func Inside(latitude float64, longitude float64, boundary polygon) bool {
    inside := false

    j := len(boundary) - 1
    for i := 0; i < len(boundary); i++ {

       xi := boundary[i][0]
       yi := boundary[i][1]

       xj := boundary[j][0]
       yj := boundary[j][1]

       // Crossing the border of the polygon?
       intersect := ((yi > latitude) != (yj > latitude)) && 
                    (longitude < (xj-xi)*(latitude-yi)/(yj-yi)+xi)

       if intersect {
          inside = !inside
       }
       j = i
    }

    return inside
}

 

Posted on

The Noble 8-fold path of development

…. or maybe not so noble,
but more a tactical assault on the problem.

  1. Slap some stuff together
  2. Understand what you did, what it does, and what it should do.
    If you don’t or it doesn’t, revert to 1…
  3. Fix the remains so it does what it was supposed to do,
    in a passable fashion.
  4. Run it by some innocent victim (aka guinea pig or co-worker),
    and see about their reaction.

    If bad, revert to step 3.
  5. Prettify, if required…(trust me, it is.)
  6. Do a QA / code review with your peers (guinea pigs),
    and when the number of Whiskey Tango Foxtrots/minute
    goes below 1, you are generally safe to proceed.
  7. Release the product.
  8. Duck/Hide under the table, wait for the client fallout and bugs to be reported.
Posted on

When things go untested…

This shows the importance of fundamental testing of code in Dev and Staging, BEFORE pushing to prod,
no matter the urgency, unless you are absolutely sure it will work and it is an emergency, or, of course,
you are out of options and ready to take the risk of burning down the house…

What could possibly go wrong, right?