DanRedux
DanRedux

Reputation: 9359

How to redirect HTTPS to insecure WS?

I may not be doing something right, security wise, so please do inform me.

User visits the site (and is forced to use HTTPS). Valid certificate. They connect via WSS to a "middleman" server. Third-party orgs expose a normal WS server to the internet, and broadcast it's public address/port to the "middleman" server, which is then broadcast to the user.

So, the user, on this HTTPS site, gets a url such as ws://203.48.15.199:3422. Is there any way I can possibly allow this sort of connection to happen?

One such way is to allow the "middleman" to also be a proxy - every third-party server address is assigned a path on the WSS-enabled middeman server. User's would connect to wss://example.com/somepath and I would simply proxy it back to the third-party, insecure websocket. The downside is that I must maintain that proxy, which defeats the purpose of allowing third-parties to even run their own server.

Any ideas?

Upvotes: 5

Views: 16447

Answers (2)

vcsjones
vcsjones

Reputation: 141678

Is there any way I can possibly allow this sort of connection to happen?

This is a form of active mixed content. All recent browsers, such as Firefox and Google Chrome prohibit this kind of content, much like they prohibit a secure page (HTTPS loaded page) from loading insecure JavaScript.

The reasoning is fairly straight forward: it undermines the purpose of HTTPS in the first place.

The "correct" way to fix this is to force all 3rd party to HTTPS on their websockets as well and avoid the whole issue.

One such way is to allow the "middleman" to also be a proxy

Yes. You could set up a proxy server for your 3rd parties that you want to allow proxying. There are numerous examples of doing this nginx scattered around the internet. A simple example might be:

# untested configuration

server {
  listen 443 ssl;
  ssl_certificate /etc/ssl/certs/cert.pem;
  ssl_certificate_key /etc/ssl/private/cert.key;

  location /3rdpartyproxy {
    proxy_pass http://203.48.15.199:3422;
    proxy_http_version 1.1;
    proxy_set_header Upgrade websocket;
    proxy_set_header Connection upgrade;
  }
}

Something like this may work, but keep in mind it is not in the best interest of your users. The connection between your proxy and the 3rd party is still insecure and vulnerable to all the same attacks that regular HTTP is.

Another thing to watch out for is to make sure your proxy isn't used incorrect by other parties. I've seen some people set a proxy with a dynamic path and would proxy that traffic to wherever. Something like:

ws://myproxy.example/203.48.15.199/3422

Then configure the web server to proxy it to whatever was in the URL. This seems like a nice solution because it'll just do the right thing depending on whatever the URL is. The major down side to it is, unless you have some kind of authentication to the proxy, anyone can use it to proxy traffic anywhere.

To summarize:

  1. You cannot allow ws: on https: pages.
  2. The best solution is to move the burden on to the 3rd parties. Have the set up proper HTTPS. This is the most beneficial because it fully serves the purpose of HTTPS.
  3. In can proxy it. The caveat being that it is still insecure from your proxy to the 3rd party, and you now need to manage a proxy server. Nginx makes this fairly easy.
  4. If you go the proxy route, make sure it's configured in a manner that cannot be abused.

If I require SSL, does this mean they won't be able to just publish an IP to connect to?

Getting an HTTPS certificate requires a domain name. To be more specific, getting a certificate for an IP address is possible, but it very out of the ordinary and far more effort than getting one for a domain name.

How much more of a burden is it?

That's mostly a matter of opinion, but it will mean picking a domain, registering it, and paying to maintain the registration with a registrar. The cost varies, but a domain can usually be had for less than $15 a year if there is nothing special about the domain.

Can the process of exposing HTTPS be entirely automatic?

Getting an HTTPS certificate is mostly automate-able now. Let's Encrypt offers HTTPS certificates for free (really, free, no strings, is now a wildly popular Certificate Authority). Their approach is a bit different. They issue 3 month certificates, but use software called CertBot that automates the renewal and installation of the certificate. Since the process is entirely automated, the duration of the certificate's validity doesn't really matter since it all just gets renewed in the background, automatically.

There are other web servers that use take this a step further. Apache supports ACME (the protocol that Let's Encrypt uses) natively now. Caddy is another web server that takes HTTPS configuration to the absolute extreme of simplicity.

For your 3rd parties, you might consider giving them examples of configuration that have HTTPS properly set up for various web servers.

I would love just a little more description on "certs for IP addresses" possibility as I feel you glossed over it.

IP addresses for certificates are possible but are exceedingly rare for publicly accessible websites. https://1.1.1.1 is a recent example.

Ultimately, a CA has to validate that the Relying Party (the individual or organization that is requesting a certificate) can demonstrate control of the IP address. Section 3.2.2.5 of the CA/B Requirements describes how this is done, but practically it is left up to the CA to validate ownership of the IP address. As such "Domain Validated" certificates are not eligible for certificates with IP Addresses. Instead, "Organization Validated" certificates, or OV, is required at a minimum. OV certificate issuance is more stringent and cannot be automated. In addition to proving ownership of the IP address, you will need to provide documentation to the identity of the Relying Party such as a drivers license for an individual, or tax documentations for an organization.

  1. Let's Encrypt does not issue certificates for IP addresses, so you would likely have to find a different CA that will issue them, and likely pay for them. Registering a Domain Name for the IP address will likely come out to be more cost effective.

  2. I'm not aware of any CA that will issue certificates for an IP address in an automated fashion like Let's Encrypt / CertBot.

  3. Using a domain name affords more flexibility. If an IP address needs to be changed, then it is a simple matter of updating the A/AAAA records in DNS. If the certificate is for the IP address, then a new certificate will need to be issued.

  4. There have been historical compatibility issues with IP addresses in certificates for some software and browsers.

Upvotes: 8

Eugène Adell
Eugène Adell

Reputation: 3174

An idea, but you still need your server to behave as a reverse-proxy : instead of example.com/somepath, implement thirdparty.example.com virtual host for each of your third parties. You then need a wildcard certificate *.example.com, but this prevents people trying to access example.com/somepathdoesntexist

Upvotes: 0

Related Questions