caddyhttp: Move HTTP redirect listener to an optional module (#4585)

This commit is contained in:
Francis Lavoie 2022-02-19 17:36:36 -05:00 committed by GitHub
parent 7778912d4e
commit 186fdba916
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 5 deletions

View file

@ -1,6 +1,7 @@
{
servers {
listener_wrappers {
http_redirect
tls
}
timeouts {
@ -32,6 +33,9 @@ foo.com {
":443"
],
"listener_wrappers": [
{
"wrapper": "http_redirect"
},
{
"wrapper": "tls"
}

View file

@ -343,11 +343,6 @@ func (app *App) Start() error {
// enable TLS if there is a policy and if this is not the HTTP port
useTLS := len(srv.TLSConnPolicies) > 0 && int(listenAddr.StartPort+portOffset) != app.httpPort()
if useTLS {
// create HTTP redirect wrapper, which detects if
// the request had HTTP bytes on the HTTPS port, and
// triggers a redirect if so.
ln = &httpRedirectListener{Listener: ln}
// create TLS listener
tlsCfg := srv.TLSConnPolicies.TLSConfig(app.ctx)
ln = tls.NewListener(ln, tlsCfg)

View file

@ -20,8 +20,45 @@ import (
"net"
"net/http"
"sync"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
)
func init() {
caddy.RegisterModule(HTTPRedirectListenerWrapper{})
}
// HTTPRedirectListenerWrapper provides HTTP->HTTPS redirects for
// connections that come on the TLS port as an HTTP request,
// by detecting using the first few bytes that it's not a TLS
// handshake, but instead an HTTP request.
//
// This is especially useful when using a non-standard HTTPS port.
// A user may simply type the address in their browser without the
// https:// scheme, which would cause the browser to attempt the
// connection over HTTP, but this would cause a "Client sent an
// HTTP request to an HTTPS server" error response.
//
// This listener wrapper must be placed BEFORE the "tls" listener
// wrapper, for it to work properly.
type HTTPRedirectListenerWrapper struct{}
func (HTTPRedirectListenerWrapper) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "caddy.listeners.http_redirect",
New: func() caddy.Module { return new(HTTPRedirectListenerWrapper) },
}
}
func (h *HTTPRedirectListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return nil
}
func (h *HTTPRedirectListenerWrapper) WrapListener(l net.Listener) net.Listener {
return &httpRedirectListener{l}
}
// httpRedirectListener is listener that checks the first few bytes
// of the request when the server is intended to accept HTTPS requests,
// to respond to an HTTP request with a redirect.
@ -112,3 +149,8 @@ func firstBytesLookLikeHTTP(hdr []byte) bool {
}
return false
}
var (
_ caddy.ListenerWrapper = (*HTTPRedirectListenerWrapper)(nil)
_ caddyfile.Unmarshaler = (*HTTPRedirectListenerWrapper)(nil)
)