Caddy: on a port using TLS, suppress the TLS alert on unexpected http requests

Created on 13 Apr 2016  ·  15Comments  ·  Source: caddyserver/caddy

version 0.8.2
This is the caddy file

0.0.0.0:9999
tls ./key/csr.pem ./key/key.pem

Calling https got the expected result, but then I call http://[[local IP]]:9999 in Chrome, then i got the following file (I zipped it)
download.zip

How could I do manually redirect from http to https ?

feature request

Most helpful comment

The library Caddy uses for TLS responds with a binary packet, which represents an error in the TLS protocol, but is interpreted as the requested content by the browser.

Google's server does respond with an empty packet, resulting in no download.

I will see if we can suppress that TLS alert easily as well.

All 15 comments

You've asked Chrome to load a page with HTTP (http://[[local IP]]:9999) but the server is serving HTTPS on that port. Your URL needs to start with https for it to work properly.

  1. If the http is not serving, it should not reply anything. That what I expected.
  2. I would like to know how to redirect the user that call http to be redirected to https as well.

Allow me to rephrase your second (feature) request: You want Caddy to redirect visitors that did not send a _TLS client hello_ (https ← http in tls) where one was expected.

Although it's possible for the http server to react to something like that (for example by serving an error page in plaintext), no browser would support a subsequent server-initiated »protocol upgrade«, even if we implemented it. ("Upgrade to TLS to proceed.")

FYI

If Caddy were to listen on two ports, 80 for http and 443 for https, you could configure this (I've replaced your 0.0.0.0 with my 127.0.0.1):

127.0.0.1:80 {
  redir https://127.0.0.1
}

127.0.0.1:443 {
  header / Strict-Transport-Security "max-age=31557600"
  tls ./key/csr.pem ./key/key.pem
}

Thanks for the correction and enlighten.

By the way, if I tried http://google.com:443 on the browser it returns error and not download anything how do I make Caddy act like that ?

The library Caddy uses for TLS responds with a binary packet, which represents an error in the TLS protocol, but is interpreted as the requested content by the browser.

Google's server does respond with an empty packet, resulting in no download.

I will see if we can suppress that TLS alert easily as well.

Go has no facilities to suppress the TLS alert. Its sending is optional according to specs.

We would need to wrap the output of tls.NewListener (server/server.go) and check the very first bytes.

  • If the incoming data is no _client hello_ (does not start with []byte{0x16, 0x03} (lazy check)) then flag the connection.
  • If the flagged connection gets as outgoing data the alert ([]byte{tls.recordTypeAlert=0x15, nn=0x03,nn=0x00–0x03, 0x00, 0x02, 0x02, tls.alertUnexpectedMessage=0x0a}), then alter the response (push an empty response), else passthrough.

This would be something like a copy of gracefulListener and gracefulConn.

Would it be possible to implement behavior similar to nginx using error code 497 to allow users to specify the behavior for HTTP requests to an HTTPS port (http://stackoverflow.com/a/14241127/2163024)?

@mrdziuban, yes to your question.

Thanks @wmark. Would it be best if I opened a new issue to track that request?

The issue is easy (»trivial«) enough for a beginner to tackle. ;-)

@wmark I spent some time looking into it, but I'm completely new to Go development and had trouble figuring it out. I'd be happy to help with more guidance, but otherwise I don't have the bandwidth to implement it myself.

@mrdziuban That's okay, since my work in #1430 steps on your toes a little here. In that PR I implement a Listener that manually reads the Client Hello, so what we can do is maybe build on that. Also, in a few days we're getting rid of the gracefulListener and gracefulConn with Go 1.8 coming out. So maybe revisit this in a week or so?

Thanks @mholt, I'll check back in a bit. I appreciate all the hard work!

Is there any interest in this now? I'm not particularly inclined to do it myself, since, frankly, nothing here is broken, and I'm not sure that a blank page is less confusing. From a technical standpoint, it's almost more confusing because it feels like something _worked_ and the server just isn't sending any data -- although that would be true, at least we can tell the server is responding with the correct protocol on that port and that the error is in the request.

You may disagree, and that's fine, but it probably won't convince me to work on it myself. This discussion can continue, if desired, and others are welcome to try to submit a PR, but any a solution will have to be thoroughly vetted for elegance and performance (and include tests) since it affects a critical part of Caddy's code.

I don't use Caddy anymore, just to manage expectations.

Afaik, nginx displays a dedicated error page in this case. Google's servers return an empty reply.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dafanasiev picture dafanasiev  ·  3Comments

mikolysz picture mikolysz  ·  3Comments

mschneider82 picture mschneider82  ·  3Comments

billop picture billop  ·  3Comments

crvv picture crvv  ·  3Comments