Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have option for HTTP redirect to HTTPS #523

Closed
ellisonbg opened this issue Jun 1, 2012 · 18 comments
Closed

Have option for HTTP redirect to HTTPS #523

ellisonbg opened this issue Jun 1, 2012 · 18 comments

Comments

@ellisonbg
Copy link

It would be nice if requests to HTTP could automatically redirect to HTTPS when SSL is enabled in a Tornado server.

@bdarnell
Copy link
Member

bdarnell commented Jun 1, 2012

If you have both HTTP and HTTPS in the same tornado process, you must be running two separate HTTPServers (of course such a feature should not be tied to whether SSL is handled at the tornado level, since you could be terminating SSL in a proxy, but since your question stipulated that SSL was enabled in tornado let's focus on this case first). You could simply give the HTTP server a different Application, one that just does this redirect.

I'm not convinced that it's worthwhile to have special-case support for a blanket http-to-https redirect, since the alternative of a separate Application is not that complicated and much more general (supporting different rules for different urls). On the other hand, this does seem more useful than the addslash/removeslash decorators.

@alekstorm
Copy link
Contributor

I'm in favor of less bloat. Writing your own redirecting Application is dead simple (and more flexible); there's no reason people need this done for them.

@minrk
Copy link
Contributor

minrk commented Jun 1, 2012

That makes perfect sense if you are running the two on different ports, but doesn't help the case of an app on a custom or random port (8000, etc.), where a user may not know whether it's http or https.

What is requested here is for someone who visits http://localhost:8888 to be redirected to https://localhost:8888, instead of the current "Error:...http request" on the server, and "324: ERR_EMPTY_RESPONSE" on the client.

Can you describe how this can be done with current tornado?

@alekstorm
Copy link
Contributor

@minrk That's not possible - HTTP and HTTPS must run on different ports. The redirection you see on other sites from http:// to https:// works because the first is on port 80, and the second on port 443 - the browser is just hiding the default port numbers from you.

@minrk
Copy link
Contributor

minrk commented Jun 1, 2012

I'm aware of the standard ports, and how that is an easy problem and one that doesn't need solving. This feature request is for the harder one of incorrect request to the actual server (port and all).

SSL is fully aware that it received a plain HTTP request when it fails (it's in the error message), so it must be possible to act on this event.

For example, CherryPy replies with a human-readable message, rather than just closing the connection.

@alekstorm
Copy link
Contributor

Interesting. OpenSSL apparently throws an exception with the description "http request" (I assume it comes to this conclusion via some heuristics once the normal SSL handshake fails). If you were going to catch this exception, SSLIOStream would be the place to do it, but that seems like the wrong place to write a response in plain HTTP.

A quick survey of Google, Facebook, and Twitter shows that none of them consider this a big enough problem to handle at all, so I think that a) you shouldn't worry about it, and b) CherryPy-like handling shouldn't be included in Tornado.

@minrk
Copy link
Contributor

minrk commented Jun 1, 2012

A quick survey of Google, Facebook, and Twitter shows that none of them consider this a big enough problem to handle at all, so I think that a) you shouldn't worry about it, and b) CherryPy-like handling shouldn't be included in Tornado.

I agree it makes little sense for a public website, which ~never would be using a manually typed port, but it certainly does for local services on a custom port. This feature request is prompted by the IPython Notebook, where this has already come up plenty of times for users as a minor annoyance.

@bdarnell
Copy link
Member

bdarnell commented Jun 1, 2012

Ultimately it's up to the user to use a correct url rather than an incorrect one. Some types of mistakes are easy to work around with a simple redirect rule, but this isn't one of them. It's possible to do something clever with this case, but it's pretty tricky and requires violating several layers of abstractions, so I think the right policy here is garbage in, garbage out.

Also consider that redirects from http to https are something of a security vulnerability since the redirect happens outside the SSL protection and is therefore subject to hijacking. In fact, you may be able to use HSTS here so that once a user has connected successfully once, their browser will remember the SSL requirement and not attempt unencrypted access in the future.

@minrk
Copy link
Contributor

minrk commented Jun 1, 2012

Fair enough. If a CherryPy-style solution is not feasible because of where tornado draws its boundaries, then that's the way it is.

garbage in, garbage out

I just have difficulty not wanting to help users, when (unlike garbage in):

  1. the error is simple and obvious (SSL fails with 'http request')
  2. the solution is simple and obvious (plain reply with "I'm https, not http!")

But I understand that with the way tornado is organized, it may not be possible for the implementation to be clean or simple.

Also consider that redirects from http to https are something of a security vulnerability

That's probably why CherryPy uses a message rather than a redirect. This would still be a huge improvement.

@alekstorm
Copy link
Contributor

On Fri, Jun 1, 2012 at 12:35 PM, Min RK <
reply@reply.github.com

wrote:

Also consider that redirects from http to https are something of a
security vulnerability

That's probably why CherryPy uses a message rather than a redirect. This
would still be a huge improvement.

Whether the server responds with a message, a redirect, or nothing at all
is irrelevant. As long as the client thinks it's speaking to an HTTP
server, an attacker can hijack the session. There's nothing you can do.

@bdarnell
Copy link
Member

bdarnell commented Jun 1, 2012

I think the real reason cherrypy uses an error rather than a redirect is that it can't know what to redirect to. OpenSSL swallowed the request so cherrypy can't see e.g. the Host header, all it knows is that some HTTP request was attempted. To redirect it would have to use some configured default address (or implement some much more complicated scheme to capture the data for HTTP use before passing it off to SSL). You could probably return an error page with a javascript redirect in it though.

@minrk
Copy link
Contributor

minrk commented Jun 2, 2012

I expect you guys aren't interested, but if ever you are, here's a quick stab at how gross such a thing might look:

minrk@831db82

Then this version of the hello world example will reply to HTTP requests on the HTTPS port with a configurable message.

I didn't know a better way to propagate an option for SSLIOStream than piggy-backing on ssl_options, but since this is just a demo, I don't think that really matters.

@dkavanagh
Copy link

Since a lot of people find this thread, I'll add what I ended up doing. I do a configurable redirector (it can be turned off in my code). I use the built-in Python BasicHTTPServer stuff. Works nicely, no tornado patches to carry, minimal overhead.

https://gist.github.com/dkavanagh/5759928

@rgbkrk
Copy link
Contributor

rgbkrk commented Jul 25, 2014

Yet again, I wish this was revisited.

@dkavanagh
Copy link

Here is a solution I used:
https://github.com/eucalyptus/eucalyptus-console/blob/maint/3.4/testing/euca-console-server#L185-L209

On Fri, Jul 25, 2014 at 10:59 AM, Kyle Kelley notifications@github.com
wrote:

Yet again, I wish this was revisited.


Reply to this email directly or view it on GitHub
#523 (comment).

@bdarnell
Copy link
Member

@dkavanagh That's a two-port solution (which you can do in tornado without multiple threads; just start two HTTPServers on the same IOLoop). This thread is about trying to do the same thing on a single port, which is only possible in a very hacky way. I'm still uncomfortable with the idea of intercepting (certain) ssl errors and doing stuff with the socket object while it's in a poorly-defined state.

@paxan
Copy link

paxan commented Aug 18, 2015

@bdarnell,
Most responders have focused on SSL aspect of this issue, which applies when a Tornado deployment aims to handle SSL and plain/text requests directly.

But if you're behind an SSL-terminating reverse proxy like Heroku HTTP router, it would still be great to have an option that acts in concert with xheaders=True to force http to https redirections.

I've cobbled together this hack as a demo.

@bdarnell
Copy link
Member

@paxan That's a fair point; the X-Forwarded-Proto situation doesn't have the fundamental problems of the single-port TLS and cleartext situation. This looks like it needs a solution that doesn't involve overriding non-public methods (although can you not configure heroku to do the http-to-https redirect for you?). It can be done cleanly today with the HTTPServerConnectionDelegate and HTTPMessageDelegate interfaces, but it's verbose. We should consider either including a wrapper for the Application that does this for you, or some extra sugar to make it easier to wrap Application. In either case, this is really a separate issue than the mixed single-port issue discussed in this thread, so it should probably be in a new github issue.

rawlins added a commit to crawl/crawl that referenced this issue Mar 19, 2024
This option lets you e.g. redirect http://server:8080 to
https://server:8443. There's various external ways of doing this, but
it's convenient when running webtiles on custom ports to simply be able
to set the redirect in webtiles options.

Note: after spending a bunch of time on this, I've concluded it's
essentially completely impossible within tornado to redirect a http to
https connection on the same port (or vice versa). It's a bit
unfortunate, as this would help with a bunch of scenarios that browsers
auto-manage when using 80/443, but it is what it is. See
tornadoweb/tornado#523 for more info. Also,
tornado just hangs when you send a https connection to a http port,
apparently before the Application code gets access; I have no idea why
this is. But probably official servers will soon no longer use http
ports at all, so maybe not a worry.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants