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

UDM Pro and SSL

So you have a Ubiquiti Dream Machine Pro (UDM pro) box, and you want to install SSL certificates?

This goes for the OS Version 3.2+

This is quite straightforward in a few single steps.

  1. Enable SSH login in the machine.
  2. Connect by SSH using “admin” and your password to the machine.
  3. do a
    cd /data/unifi-core/config
  4. In there, do a backup:
    tar zcvf backup.tgz *
    and download this file (sftp / scp).
    scp [email protected]:/data/unifi-core/config/backup.tgz .
  5. in there, you should find the following files: 
    unifi-core-direct.crt
    unifi-core-direct.key
    unifi-core.crt
    unifi-core.key
  6. Make a copy of your SSL key, and rename it as unifi-core.key and unifi-core-direct.key
  7. Create a new file called unifi-core.crt, and in this file, you copy in your certificate
    followed by the root CA bundle from your certificate issuer, such as :
    <certificate_file>
    <bundle_file>
    and save it, then copy the file unifi-core.crt to unifi-core-direct.crt 

    Here’s the command line steps to create the files for all above:
    cat cert.key > unifi-core.key
    cat cert.key > unifi-core-direct.key
    cat cert.pem > unifi-core.crt
    echo "" >> unifi-core.crt
    cat cert.ca-bundle.pem >> unifi-core.crt
    cp unifi-core.crt unifi-core-direct.crt

  8. Upload the files (sftp/scp) to the folder /data/unifi-core/config
    scp unifi-core-* [email protected]:/data/unifi-core/config/
  9. On your UDM pro, issue the command:
    systemctl restart unifi-core
    You should now be able to connect to the machine using the https and certificate.
    Note that you may need to point out the address in your DNS, or add the IP in your lmhosts/hosts file,
    such as 192.168.0.1 gw.<domain.tld>

That should be it, and you should have a working SSL certificate on the box.
Note that updates of the OS, may reset the files, so keep them handy.

Good luck!