I wrote up a load balancing script that queries an api to get a list of ip address of healthy vms, and everything worked great in the editor. However, when I saved it and tested it live, I would always get an error that says “Direct IP access not allowed”.
I got around that by using a reverse ip hostname (i.e. x.x.x.x.bc.googleusercontent.com). But then, I was also using arbitrary port numbers for my services, and it would just give me an error saying that it failed to connect to the server. This also reveals my hostname, which, ideally, would be kept private.
So, I changed the all the ports to 80. The requests are finally getting through, but it seemed like not all of my headers were being sent. (i.e. Host and X-Forwarded-Proto) I double checked this with httpbin.org/headers.
All of these things make it seem like workers aren’t as powerful as it’s been made out to be. Is it really necessary to make fetch so restrictive?
Additionally, it would be very helpful if the editor testing would succumb to the same restrictions as it does live. Documentation about them would be great too.
I’m sorry to hear that you’ve run into so many of our sharp edges – I know how frustrating it can be, and I really appreciate the time you spent writing up your experience, because it helps us learn and improve our service. We definitely have some limitations, and we’d like to lift them as we are able to.
At this time we do not allow direct IP access via fetch(). Although it is technically possible for us to lift this restriction, we must perform a thorough security review of the implications on our infrastructure before we can do so. This will take time, so I cannot guarantee that it will happen by any particular date.
The reverse IP hostname is a nice trick! Regarding the error revealing your hostname, it may be necessary to sanitize certain 5xx errors which Cloudflare returns before returning them to the eyeball. This would probably be necessary even if direct IP access worked, since an origin connection error could still occur in that case, potentially revealing the origin IP.
I think that not being able to use arbitrary ports on an external service is a bug, but I’m still trying to confirm – there may be some rationale for disallowing it that I’m unaware of.
Neither of the two headers you listed can be directly controlled – the Workers runtime will overwrite both of them, since it emits host-style HTTP requests, which it must construct from the absolute URL passed to fetch(). However, both headers should indeed be sent. httpbin.org/headers does not seem to expose X-Forwarded-Proto, but it does expose the Host header, at least when I tested it.
To verify that X-Forwarded-Proto is sent (and correctly reflects the eyeball <-> Cloudflare connection protocolEdit: @ssttevee points out in the next post that it is actually derived from the scheme of the URL passed to fetch()), I configured nginx on my origin with an access log like so:
When I curl http://my-domain.com, I see an access log of the form "my-domain.com" "http" logged at my origin. When I curl https://my-domain.com, I see "my-domain.com" "https" logged at my origin. Are you able to perform a similar test?
I presume the default value of X-Forwarded-Proto (reflecting the connection protocol between the eyeball and Cloudflare) should suffice for your use case, but I understand the need to override the Host header. The best I can offer here might be to point you to the Resolve Override feature:
However, Resolve Override can only resolve to orange-cloud records on your zone, so using this would require you to make an A record for each IP you want to load balance across, which might not be feasible.
I hear you, and we’re working on both making the preview service more accurate and documenting all of these restrictions.
No. I know that we return 500, 502, 504, and 520-526, inclusive, but I’m unaware of an exhaustive list in our documentation. If you need to sanitize the error pages, I’d recommend unconditionally replacing the bodies of 5xx responses with your own text.
Thanks for pointing this out; I was mistaken: X-Forwarded-Proto takes its value from the URL passed to fetch() (except same-zone subrequests with a Flexible SSL setting, which always take the value “http”, it seems).
At this time we do not allow direct IP access via fetch()
Hello, is there any discussions on this issue? I’m running through similar problems trying to export some logs from CF to Elasticsearch. It would be a great improvement to allow fetching IPs directly, as we don’t want to expose our instances’ IPs to the world.
Given that Cloudflare doesn’t support zone export, I believe if you put it under an unguessable cname it should be no easier for someone to discover than the IP Address itself. That said, a truly secure way to do this might be to use the combination of Argo Tunnel and Cloudflare Access.
Is there any update on this? Especially interested in the direct IP access. Reverse IP services are unstable (at least the ones we tried), and creating DNS records for every server in an autoscaling environment is troublesome.
Passed two years again, Is there any update on this?
Hope to support fetch ip resources directly than domain. please consider it
In china mainland, network restricted more than most countries in the world, we can’t visit most popular websites such as G, F, T, Y.
If we built a web site by myself, no matter what to do even though tech forum or personal blog, gov require all company and person provide many id infos to use domain in vps, otherwise, only ip:port could be use. This operation called “备案” in chinese. All of us hate it.
As a personal, Even if we are willing to give up personal privacy to provide infos to censor, But only a few kinds of domain could pass. such as “.com, .cn, .org”, Unfortunately, my domain is “.me”, It’s can not to be approved always.
If CF’s workers could reverse proxy resources from ip directly, this will help us to bypass censor. Hope to support it, thanks.
You can get around the IP address limitation by using a free service like Deno Deploy (free) or Fly.io (free level). They give you a free domain (example: myapp.deno.dev). There, you can write a script that gets the data from your ip address, await fetch("http://11.222.333.444"). Then, in your CF Worker script, you can await fetch( "https://myapp.deno.dev ") .
IP Address <-> deno/fly.io/etc. <-> CF Worker <-> Your audience.
I also live in China and have to deal with this regulation you mentioned. Theres some simple & free solutions you might not have considered but are not relevant to this thread. 加我微信15828144424