Worker cannot connect to custom port

According to this thread it should be working and yet I’m having the error.

So my setup is like this:

I have a gray-cloud A record my.domain.com in my Cloudflare zone pointing to my server IP.
The server is listening at port 8080 that serves a HTTP website.

On my local machine, I verified the HTTP server is live, and the DNS is working, by doing this:

curl http://my.domain.com:8080/

And it returns the page successfully.

Then I setup my Worker script like this:

addEventListener('fetch', event => {
  event.respondWith(fetch('http://my.domain.com:8080/'))
})

If I run the script in the online editor, it works and renders the page successfully inside the editor environment.
However if I publish the Worker, and access it from my local machine:

curl https://myworker.workers.dev/

Then it returns 521 Origin Down error.

I tried several things and it seems only port 80 is working for the published Worker, while any arbitrary port works inside the online editor environment.

My goal is to use port 8080 in the published Worker script. Please advise how can I get it working.

If the ‘my’ record is set to :grey: in DNS, does it work?

Would you happen to have “Always Use HTTPS” enabled in the SSL/TLS Edge Server section? If so, that Browser test probably would have redirected to HTTPS.

As I mentioned, it’s already a gray-cloud A record. And I checked “Always Use HTTPS” is already off.
The very fact that the online Worker editor environment works means the route is clear.
So the only reason it could be is Cloudflare is deploying a different set of outgoing request filtering policy in published Worker environment than the development environment.
And according to this thread I linked, Cloudflare had allowed this policy before. So I guess maybe some regression reverted this policy in their production environment.

1 Like

I can confirm to you that the specific worker is still in production on my end, and works just fine.

I presume the issue is that you should use exactly my code and not put the :8080 which if I recall correctly fails. Copy and paste my code, exactly, you don’t even need to change anything except the specific port.

You will need to set the record to :orange: and have the SSL mode correctly set (if it’s Full or Full (Strict) with an HTTPS connection on the user’s side it will connect via HTTPS. That would be the a pain. Use HTTPS on both sides.

1 Like

So I tried all these things you mentioned and still not working:

  1. I setup letsencrypt certificate on the server, so :8080 serves a HTTPS server with a certificate of my.domain.com.
  2. I enabled Full (Strict) SSL mode, and switched my.domain.com to :orange:.
  3. I changed Worker script to yours:
addEventListener('fetch', event => {
  const request = event.request;
  const url = new URL('https://my.domain.com/');
  url.port = 8080;
  event.respondWith(fetch(url, request));
});

Now if I run the Worker script in online editor environment, it returns:

Error communicating with origin server my.domain.com:8080
OpenSSL error; message = error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER

And if I access the published Worker directly I get Error 521 Web server is down. If I visit https://my.domain.com:8080 I get Error code: SSL_ERROR_RX_RECORD_TOO_LONG in Firefox.

However I can verify that my SSL certificate is valid, and HTTPS server code behaves correctly, by changing the listening port to 443, and the Worker script port to 443 as well, then everything works. But just changing the port back to 8080 it fails with above errors again.

@zack @KentonVarda Could you have a look please?

Let me get a bit of clarification.

  1. Which port do you want on the user’s side? Meaning, what does one put in the browser?
  2. Are you now running HTTPS on port 8080 on the origin?
  1. I want the user to type in their browser https://myworker.workers.dev (:443). Which should be forward by the Worker script to http(s)://my.domain.com:8080. Either HTTP or HTTPS on the origin is fine with me, which ever works is fine.
  2. Yes, after your suggestion I enabled HTTPS (letsencrypt TLS certificate) on port 8080 on the origin.

Ok, first possible issue, when you do that you are sending a request to port 8080 of your server, requesting myworker.workers.dev. This, if the server is correctly configured, won’t work. You either need to put the worker directly on that URL or make sure the server replies to that subdomain.

Port 8080 is normally HTTP only, activate it on port 8443.


Is there a specific reason why you aren’t putting this service on port 80/443? It makes things way easier.

I’m not sure what you suggest here. Are you saying I should add a worker route on my.domain.com/* to the worker script? I tried it just now and accessing both https://myworker.workers.dev and https://my.comain.com it’s still Error 521 Web server is down. I also tried changing to 8443 but got the same error.

There are many technical and policy reasons I can’t use 80/443. I can’t get into too much details but it has something to do with our production architecture and this specific worker script we are writing.

Gotcha, no worries, but sometimes it happens that not asking the simplest questions leads to longer issues ahah


Correct, but I found a couple issues in your code:

url can’t be a const and doing it this way you loose the path.

Change it to (apparently host includes the port if you put it there, my bad):

addEventListener('fetch', event => {
  const request = event.request;
  var url = new URL(request.url);
  url.host = 'my.domain.com:8443';
  event.respondWith(fetch(url, request));
});

Can you try doing a cURL to the origin server, on the correct port (if you use HTTPS leave it at 8443), with an Host header of your worker’s URL? This last code, if run directly on the correct URL, should work. If run on the Worker’s URL it may not, unless you:

Ah there’s a typo in the route I added. After I fixed that it works! The Worker script I had works fine.
So the problem here is indeed the worker route, and has to be :orange: cloud. I tried change it to :grey: and it doesn’t work again. I don’t know why @KentonVarda suggested :grey: would work.

But anyway thanks for helping out. It’s working for my use case now.
Cheers!

I realized later that const actually works here, as it’s not technically reassigned.

Because the worker doesn’t run if it’s :grey:.

He didn’t, @zack did, but it isn’t the case. I believe he though it needed to resolve DNS of another record to go directly to the origin instead of passing through Cloudflare’s proxy again. That is not the case since once you are on the edge you will go directly to the origin if you query records within the same zone. Any record.

My case, the worker still go to 443, no matter the port I set in the code.

I faced the error and saw the URL has HTTPS instead of HTTP.
So I just replaced it and worked!.

  url.href = url.href.replace('https','http');
  url.host = myurl+':9091';
  event.respondWith(fetch(url, request));

Ok, first possible issue, when you do that you are sending a request to port 8080 of your server, requesting myworker.workers.dev . This, if the server is correctly configured, won’t work. You either need to put the worker directly on that URL or make sure the server replies to that subdomain.

But why would a content (origin) server ever see the myworker.workers.dev host header? Doesnt CFW runtime replace/ignores the JS set host header universally on a outgoing req to a content server? See Not possible to override the Host header on Workers requests

If you request the domain myworker.workers.dev, it will forward that to the origin. You can’t change the Host header to other website, especially if they aren’t active on Cloudflare on your own account.

1 Like