If client sent an HTTP request to an HTTPS server port
, returns 302 redirection, like nginx's "error_page 497".
Related issue: golang/go#49310
Simple version: simplehlfhr
go get github.com/bddjr/hlfhr
flowchart TD
Read("Hijacking net.Conn.Read")
IsLooksLikeHTTP("First byte looks like HTTP?")
Continue(["β
Continue..."])
ReadRequest("π Read request")
IsFindHostHeader("Find Host header?")
IsHandlerExist("`
HttpOnHttpsPort
ErrorHandler
exist?`")
302Redirect{{"π‘ 302 Redirect"}}
Handler{{"π‘ Handler"}}
Close(["β Close."])
Read --> IsLooksLikeHTTP
IsLooksLikeHTTP -- "πfalse" --> Continue
IsLooksLikeHTTP -- "πtrue" --> ReadRequest --> IsFindHostHeader
IsFindHostHeader -- "βfalse" --> Close
IsFindHostHeader -- "β
true" --> IsHandlerExist
IsHandlerExist -- "βfalse" --> 302Redirect --> Close
IsHandlerExist -- "β
true" --> Handler --> Close
// Use srv.ListenAndServeTLS
func main() {
// Use hlfhr.New
srv := hlfhr.New(&http.Server{
Addr: ":5678",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Write something...
}),
ReadHeaderTimeout: 10 * time.Second,
})
// Then just use it like http.Server .
err := srv.ListenAndServeTLS("localhost.crt", "localhost.key")
fmt.Println(err)
}
// Use srv.ServeTLS
func main() {
// Use hlfhr.New
srv := hlfhr.New(&http.Server{
Addr: ":5678",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Write something...
}),
ReadHeaderTimeout: 10 * time.Second,
})
// Then just use it like http.Server .
l, err := net.Listen("tcp", srv.Addr)
if err != nil {
fmt.Println(err)
return
}
defer l.Close()
// Must use ServeTLS! For issue https://github.com/bddjr/hlfhr/issues/4
err = srv.ServeTLS(l, "localhost.crt", "localhost.key")
fmt.Println(err)
}
// Use hlfhr.NewListener
func main() {
srv = &http.Server{
Addr: ":5678",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Write something...
}),
ReadHeaderTimeout: 10 * time.Second,
}
l, err := net.Listen("tcp", srv.Addr)
if err != nil {
fmt.Println(err)
return
}
defer l.Close()
// Use hlfhr.NewListener
var httpOnHttpsPortErrorHandler http.Handler = nil
l = hlfhr.NewListener(l, srv, httpOnHttpsPortErrorHandler)
// Must use ServeTLS! For issue https://github.com/bddjr/hlfhr/issues/4
err = srv.ServeTLS(l, "localhost.crt", "localhost.key")
fmt.Println(err)
}
// 307 Temporary Redirect
srv.HttpOnHttpsPortErrorHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hlfhr.RedirectToHttps(w, r, 307)
})
// Check Host Header
srv.HttpOnHttpsPortErrorHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hostname, port := hlfhr.SplitHostnamePort(r.Host)
switch hostname {
case "localhost":
//
case "www.localhost", "127.0.0.1":
r.Host = hlfhr.HostnameAppendPort("localhost", port)
default:
w.WriteHeader(421)
return
}
hlfhr.RedirectToHttps(w, r, 302)
})
// Script Redirect
srv.HttpOnHttpsPortErrorHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(300)
io.WriteString(w, "<script>location.protocol='https:'</script>")
})
srv := hlfhr.New(&http.Server{})
srv := hlfhr.NewServer(&http.Server{})
var srv *http.Server
isShuttingDown := hlfhr.IsHttpServerShuttingDown(srv)
var srv *hlfhr.Server
isShuttingDown := srv.IsShuttingDown()
var l net.Listener
var srv *http.Server
l = hlfhr.New(srv).NewListener(l)
var l net.Listener
var srv *http.Server
var h http.Handler
l = hlfhr.NewListener(c, srv, h)
var l net.Listener
isHlfhrListener := hlfhr.IsMyListener(l)
var c net.Conn
isHlfhrConn := hlfhr.IsMyConn(c)
b := []byte("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n")
looksLikeHttp := hlfhr.ConnFirstByteLooksLikeHttp(b[0])
var c net.Conn
var b []byte
n, err := c.Read(b)
br := hlfhr.NewBufioReaderWithBytes(b, n, c)
var w http.ResponseWriter
hlfhr.Redirect(w, 302, "https://example.com/")
var w http.ResponseWriter
var r *http.Request
hlfhr.RedirectToHttps(w, r, 302)
hostname, port := hlfhr.SplitHostnamePort("[::1]:5678")
// hostname: [::1]
// port: 5678
hostname := hlfhr.Hostname("[::1]:5678")
// hostname: [::1]
port := hlfhr.Port("[::1]:5678")
// port: 5678
Host := hlfhr.HostnameAppendPort("[::1]", "5678")
// Host: [::1]:5678
Host := hlfhr.ReplaceHostname("[::1]:5678", "localhost")
// Host: localhost:5678
Host := hlfhr.ReplacePort("[::1]:5678", "7890")
// Host: [::1]:7890
v6 := hlfhr.Ipv6CutPrefixSuffix("[::1]")
// v6: ::1
git clone https://github.com/bddjr/hlfhr
cd hlfhr
./run.sh
https://developer.mozilla.org/docs/Web/HTTP/Session
https://developer.mozilla.org/docs/Web/HTTP/Methods
https://developer.mozilla.org/docs/Web/HTTP/Redirections
https://developer.mozilla.org/docs/Web/HTTP/Status/302
https://developer.mozilla.org/docs/Web/HTTP/Status/307
https://developer.mozilla.org/docs/Web/HTTP/Headers/Connection
https://tls12.xargs.org/#client-hello
https://tls13.xargs.org/#client-hello
https://nginx.org/en/docs/http/ngx_http_ssl_module.html#errors
golang/go#49310
golang/go#66501
"net/http"
"net"
"crypto/tls"
"reflect"