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

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 ?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (3 by maintainers)

Most upvoted comments

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.

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
}

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.