Using resolveOverride raises error 1034 Edge IP Restricted on some requests

Background:

  • I have a name in my Cloudflare zone (example.com) that is presently a CNAME to a Hubspot name; let’s call it go.example.com with the CNAME target 23233.group99.sites.hubspot.net
    • I don’t know if HS is a Cloudflare customer (an “orange-to-orange” problem), the real version of the above hubspot.net currently does not resolve to a Cf address
  • the Hubspot origin requires the host header to be go.example.com; sending 23233.group99.sites.hubspot.net or anything else returns 404
  • I need to now “share” that name with another provider Unboundpages who also have the same requirement - both assume total ownership of the CNAME
  • by “share” I mean send requests to either HS or UP depending on the initial part of the URL path

Attempted Solutions

Simple page rules, e.g. HTTP Redirect, won’t work as the Host header needs to stay as go.example.com.

Cloudflare page rules don’t work as using a proxy for a CNAME to a target outside my domain is prone to breaking (ref. Proxy for CNAMEs considered dangerous: “Record is managed externally” means if you proxy any CNAME to third party, you're going to have a bad time); even if that wasn’t a problem - and it is - it still wouldn’t work as that also (rightly) sets the host header correctly to the name of the origin.

So - Workers and resolveOverride - should be perfect, as the equivalent for curl works great:

% curl --silent --output /dev/null --write-out '%{response_code}\n' --connect-to go.example.com:443:hs.go.example.com:443 https://go.example.com/path/to/resource
200

(note I have created CNAMEs in my zone for the two origins, hs.go.example.com and up.go.example.com, per the resolveOverride doc Request · Cloudflare Workers docs)

And when I use the worker below to do the same thing, it sort of works some of the time.

You’ll see in the example below I have a “canary” set up using httpbin. httpbin.example.com is a CNAME pointing to httpbin.org; an example request of go.example.com/h/get should be directed to httpbin, and httpbin should echo back a url of go.example.com/get (stripping the h from the path) - and indeed it does:

% curl --silent curl https://go.example.com/h/get  | jq .url
"https://go.example.com/get"

I can execute requests against httpbin all day long. Happy days it works.

Except when it doesn’t.

When executing requests that hit the HS origin, many of them work fine, but many don’t. Seems that images are the main culprits. From what I can tell, requests that fail return a Cloudflare 1034 Edge IP Restricted ​​error.

I’m guessing that a) Hubspot is a Cloudflare customer, and b) they have Cloudflare processing enabled for some paths, and c) there’s some problem with fetches back to Cloudflare customers, at least with a resolveOverride in place.

Am I missing something?

export default {
  async fetch(request) {
    const DEFAULT_ORIGIN = 'hs.go.example.com';
    const ORIGINS = {
      'h': { origin: 'httpbin.example.com', strip: true },  // testing
      'hs': { origin: 'hs.go.example.com', strip: false},
      'kb': { origin: 'kb.go.example.com', strip: false},
    }
    let origin = DEFAULT_ORIGIN;

    const url = new URL(request.url);
    const path = url.pathname.split('/');

    // paths always start with '/': 0th element is always '', key is 1st
    const k = path[1];
    if (k in ORIGINS) {
      origin = ORIGINS[k].origin;
      if (ORIGINS[k].strip) {
        // reassemble the path omitting the 0th and 1st elements ('', key)
        url.pathname = path.slice(2).join('/');
      }
    }
    console.log(`origin: ${origin}  k: ${k}  url: ${url.toString()}`);

    const newRequest = new Request(url.toString(), {cf: { resolveOverride: origin } });
    return fetch(url.toString(), newRequest);
  },
};

I’ve confirmed that the traffic that is misbehaving is indeed being served by Cloudflare (Hubspot appear to own their own netblock but at least part of that’s being served by Cloudflare). I’ve raised a Cf support ticket on this: 3062607, asking if this is an “orange to orange” problem, and if it’s just going to break in unpredictable ways depending on how Hubspot have configured their Cloudflare zone.

Cf support have advised the resolveOverride to a name outside your zone is only intended to work for Enterprise plans. (except they don’t document that). That’s not actually true as it demonstrably works fine for non-Cf targets, i.e. this is definitely an orange-to-orange problem and I presume being on an Enterprise plan carries some kind of blessed “I can be trusted” attribute (with $ substituting for a solemn promise not to abuse the feature…). If you’re just a regular pleb Business customer, you’re SOL.

i.e. the documentation for Request Request · Cloudflare Workers docs should say

resolveOverride
… If you need to direct a request to a host outside your zone (while keeping the Host header pointing within your zone), and you are on the Enterprise plan first create a CNAME record within your zone pointing to the outside host, and then set resolveOverride to point at the CNAME record.