Apache - Force https by default on custom port

Sorry but as far as I know this can't be done by using either htaccess or the virtual host by Apache, as NON-SSL and SSL both have to have their own dedicated port, they can not share a port and its impossible for a browser to communicate with a server using the wrong protocol.

Most websites will use port 80 and 443, these ports do not appear in the address bar and therefore when you connect to http your actually connecting to http://example.com:80 and with a SSL enabled site you connect to https://example.com:443. So when you see a site redirect from HTTP to HTTPS its happened over two ports, not one.

You can have:

  • http://example.com:80 redirect to https://example.com:443

You can not have:

  • http://example.com:443 redirect to https://example.com:443

cPanel by default will use these ports:

2082    TCP CPanel default
2083    TCP CPanel default SSL

The major problem is the browser expecting the data to be either HTTPS or HTTP based on the address typed into the action bar unless a redirect is actioned but then the browser is notified of the protocol change. Since you can't connect to action that redirect the browser will fail. I'm fairly confident if there was a way then Apache or cPanel would support it and have it documented somewhere.

I'm not saying it can't be done entirely, but it can't be done on the Apache or cPanel level. I'd imagine you would need something sitting in-between both the user and Apache which monitors the packets and then does something with it, other than that I can't speculate any further or tell you a full solution.


I don't believe you can do this directly with Apache. Once you tell it you're using SSL (or actually TLS) on a port, it will expect a TLS negotiation to happen, and things will break if the browser sends "regular" HTTP rather than TLS.

Theoretically, it should be possible to have something listen on that port, detect from the first few bytes if it's regular HTTP or TLS, and act accordingly: if it's HTTP, send back a redirect, otherwise actually start TLS (either directly and then proxy/tunnel the cleartext contents to Apache, or just forward the whole encrypted stream to Apache transparently).

I was not aware of any software doing anything like this out of the box, but it seems that Nginx actually does support it, see https://stackoverflow.com/a/15435799/3527940 for an example.


As Simon has already pointed out (and you surmise in your question), this does not seem to be possible directly from the server. Since a request for http://example.com:2083/ simply can't be handled by the server (when it already handles https://example.com:2083/). As the response indicates, it's simply a "Bad Request".

Any solution would need to come from the client end (or some intermediary device) that knows to "upgrade" the request, before actually making the request to your server. There are browser extensions that might be able to handle this - but I suspect that installing something on the client is not desirable (or even possible).

There is the HTTP Strict Transport Security (HSTS) policy that instructs the client to always request the HTTPS version of the site in subsequent requests. However, this has some caveats which I can't see workarounds for in your case:

  1. this requires the user to have already successfully requested the HTTPS version (at which point the Strict-Transport-Security response header is sent informing the client that all future requests to this host must be HTTPS).

  2. HSTS is for when the host uses only SSL. All HTTP (non-SSL) requests will be upgraded. There is no HTTP anymore. Which means that http://domain.com:2082/ will not be accessible either. The browser will try to upgrade this request to https://domain.com:2082/ (yes, wrong port - see below) - this request will now break.

  3. As seen in the above point, HSTS does not really work with non standard ports (ie. ports other than 80/443). For non port 80 requests, the port number is preserved in the request. So, as stated above, port 2082 stays as port 2082. (Because the intention is that everything is now HTTPS.)

(Aside: I've not really studied the spec, but I wonder why the desired port couldn't be set as part of the initial Strict-Transport-Security response header, or have an option/flag that instructs the browser to direct requests back to the same port as the initial "successful" request? This would seem to get around points #2 and #3 above?)

So, the same conclusion as Simon, this does not seem to be possible.

Custom 400 Bad Request ...?

Just a thought... you could try defining a custom 400 ErrorDocument to have a more meaningful message and perhaps a link (or even JavaScript redirect?). However, this would need to be defined directly in the main server config to stand any chance of being triggered. (But it's not always possible to override some system generated Apache errors anyway.) And I would think you would need to specify an absolute URL in order to trigger an external redirect to another site (which will naturally lose the error status). Even if this "works", I'm not sure that it would necessarily be a good idea. (?)

Tags:

Apache