4

I am hosting a control panel for web management on a second Apache instance that runs on port 2083. It has port 2082 for the HTTP version of the site because it needed something to run the HTTP version on but the port is closed. When the user connects to the site like so:

https://example.com:2083/

They see the web panel. However, when they visit the site like this:

http://example.com:2083/

They get the error

Bad Request

Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

There is no link to click to continue. Instead of showing this error, I would like to automatically force the HTTPS protocol on the URL so they use the secured version of the portal. Since 2083 is being used for the SSL port on this panel, it causes a conflict if they don't specify HTTPS. And using the .htaccess file to add a redirect does not work since the port is loaded and sees the error before it loads anything else, ending there without ever reading the .htaccess file.

I am running Apache 2.4.23 on both the main version of the site (hosted on a Windows machine) and on the control panel. As far as I am aware this is the newest available model for a win64 model machine.

Is there any way to force the HTTPS before it loads anything else?

Here is the current httpd-ssl file

Listen 2083
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
SSLProxyCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
SSLHonorCipherOrder on 
SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLPassPhraseDialog  builtin
SSLSessionCache "shmcb:c:/panel/logs/ssl_scache(512000)"
SSLSessionCacheTimeout  300
<VirtualHost *:2083>
    SSLEngine on
    SSLCertificateFile "c:/panel/conf/ssl/sslcert.crt"
    SSLCertificateKeyFile "c:/panel/conf/ssl/sslcert.key"
    SSLCertificateChainFile "c:/panel/conf/ssl/sslcert.ca-bundle"
    ServerName https://sitename.com
    ServerAlias www.example.com
    DocumentRoot "c:/panel/htdocs/"
</VirtualHost>
  • What is your current Virtualhost file? Can you please edit it into your question? Change your real hostname to domain.com if you like, that part isn't important. – Tom Brossman Feb 2 '17 at 15:12
  • ServerName https://sitename.com ServerAlias www.example.com Is this inconsistency intended, or a result of mistakes in editing? – TRiG Feb 15 '17 at 15:50
  • Just an editing remark, they match internally – Kaboom Feb 15 '17 at 20:11
4

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. (?)

  • Good update but Apache wont recognize the error document because its hard coded to give this error response. If i could modify my source i might be able to modify that instead of outputting an error and redirect, but i guess it will have to be okay as it is since I'm not in the mood to try and wreck my Apache coding lol. – Kaboom Feb 2 '17 at 17:12
6

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 am aware you cannot use http and https on the same port. That's the whole point of this post. If you read what I said in the OP, my site is running on one version of apache which uses port 80 and 443 for its service already. The control panel runs on a SECOND apache which is using 2083 for its https port. Since 2083 isnt the default https port, if they dont use domain.com:2083 and use http then they get the error. Instead of seeing an error i would like them to be redirect to the https version by default. – Kaboom Feb 2 '17 at 15:06
  • 1
    please stop using port 463... thats why i edited your post to begin with. its port 443. – Kaboom Feb 2 '17 at 15:07
  • Can't be done... you would need to catch the protocol before Apache. – Simon Hayter Feb 2 '17 at 15:07
  • Due to the fact they are different protocols they have no way of communicating with one another, its like trying to use a FTP client to connect to a website, it can't be done. The problem is the browser, not the server, if the browser checked for non SSL then tried SSL then it would work, but browsers do not. And just FYI I did read your question, The answer I left was for you and future visitors, so if I repeated what you said or if you already know what I've wrote, great but maybe it'll help others whom that are not so technical minded about ports and protocols. – Simon Hayter Feb 2 '17 at 15:12
  • 1
    @TomBrossman fixed and thanks... happened because I got it wrong once and then copied that wrong all over my answer :) – Simon Hayter Feb 2 '17 at 15:40
5

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.

0

I've just had the same problem on Apache/2.4.6

I've added the ErrorDocument in vhost config. So it is redirecting to https in case of error 400 - this is the one behind the message visible in browser It seems to do the trick. I no longer get this error message that was posted in original question

<VirtualHost *:2083>
ErrorDocument 400 https://example.com:2083/
</VirtualHost>

Almost a year has passed since original question. Hope this will be a hint to anyone... It was mentioned before with a remark that it is hardcoded - something has changed since then

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.