nodejs/node

ability to serve both HTTP and HTTPS on the same port

Closed this issue · 8 comments

Consider the use case of an HTTPS server which is not running on port 80 or 443.

If a user connects using HTTP, the connection hangs since the server is listening for the HTTPS protocol only. A more ideal scenario would be sending an HTTP response redirecting them to use the HTTPS protocol instead.

It's possible to serve both HTTP and HTTPS on the same port. A TLS handshake record starts with byte 22, so you can use that to determine which protocol the client is trying to speak.

io.js's internal HTTP(S) parser(s) should incorporate this into their state machine and expose this API.

See andrewrk/groovebasin#401 for an example use case.
See also http://stackoverflow.com/questions/22453782/nodejs-http-and-https-over-same-port/23975955

I don't know if this may be good. SSL connections already use more CPU, adding another layer of decision for all the requests may be a bad idea.

I don't know why you're using the word "layer". We're talking about exactly 1 additional conditional branch.

https://github.com/mscdex/httpolyglot

I don't know if this should be a core or user-land feature, though.

-1. The way this issue is worded, mixing secure / insecure traffic on the same port is not something you want to do from a security point of view. HTTP / HTTPS are specified to run on distinct ports by design. At most you might want to do what nginx does and return an HTTP 400 Bad Request "Plain HTTP request sent to HTTPS port" (I think this is what you're really suggesting in your opening comment). The right way to deal with this imho is to run production systems behind a reverse proxy or firewall that will terminate the standard 80/443 http/https ports and proxy to your non-standard unprivileged ports. Then you can easily set up a redirect for http to https.

io.js is making an abstraction for http and https. It is therefore the abstraction's job to support the things that the underlying technologies support. The underlying technologies support serving both HTTP and HTTPS on the same port. Therefore the abstraction should support this.

The “underlying technologies” (an HTTP parser? OpenSSL?) don’t support serving both HTTP and HTTPS on the same port. They allow for that possibility in the same way that Node can fulfill a few functions. (Write a module if it’s important to you!)

@andrewrk Non sequitur; ports are meant to uniquely identify a network protocol. Look into how Apache implements port forwarding for the use case you described. You can also use iptables:

   iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
   iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000

and then you just set up a redirect at port 8080 to https://...

[update]
There is RFC 2817 to upgrade an HTTP connection to TLS, but it isn't widely used (and its susceptible to man-in-the-middle attacks). You might want to update the title of the issue to something like "support for RFC 2817" if you really feel its needed...?

httpolyglot module looks sufficient. Thanks @jonathanong