Below is some “redirect HTTP to HTTPS” code essentially as taken from several blogs / Q&As.
The issue I experience is that the first protocol to execute its ListenAndServe[TLS]()
function blocks or hides the other. I.e. if TLS starts on port 443 first then I see no listener - and no response - on port 80. And vice-versa. The behaviour is the same on both Ubuntu 16.04 and Windows 10. I’m using 1.10.
Any help/advice/suggestions definitely appreciated,
Thanks!
package main
import (
"crypto/tls"
"fmt"
"net/http"
"log"
"time"
)
func main() {
//
// Entire site is on HTTPS
//
smux := &http.ServeMux{}
smux.HandleFunc( "/", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf( w, "Hello, world" ) } )
tlsConfig := &tls.Config{
// Causes servers to use Go's default ciphersuite preferences,
// which are tuned to avoid attacks. Does nothing on clients.
PreferServerCipherSuites: true,
// Only use curves which have assembly implementations
CurvePreferences: []tls.CurveID{
tls.CurveP256,
tls.X25519,
},
MinVersion: tls.VersionTLS12,
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
// Best disabled, as they don't provide Forward Secrecy,
// but might be necessary for some clients
// tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
// tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
},
NextProtos: []string{"http/1.1"}, //"h2",
} // tlsConfig
cert, err := tls.LoadX509KeyPair( ".\\tiers\\staging\\server.crt",
".\\tiers\\staging\\server.key" )
if err != nil {
log.Fatal( err )
} // if
tlsConfig.Certificates = append( tlsConfig.Certificates, cert )
tlsConfig.BuildNameToCertificate()
httpsServer := newServer()
httpsServer.Addr = ":443"
httpsServer.TLSConfig = tlsConfig
httpsServer.TLSNextProto = make( map[string]func(*http.Server, *tls.Conn, http.Handler), 0 )
httpsServer.Handler = smux
go log.Println( httpsServer.ListenAndServeTLS( "", "" ) )
//
// Redirect all HTTP requests to HTTPS
//
httpServer := newServer()
httpServer.Addr = ":80"
httpServer.TLSConfig = &tls.Config{}
hmux := &http.ServeMux{}
hmux.HandleFunc( "/", func( w http.ResponseWriter, req *http.Request ) {
w.Header().Set( "Connection", "close" )
url := "https://" + req.Host + req.URL.String()
http.Redirect( w, req, url, http.StatusMovedPermanently )
})
httpServer.Handler = hmux
log.Println( httpServer.ListenAndServe() )
} // main
func newServer() *http.Server {
// set timeouts so that a slow or malicious client doesn't
// hold resources forever
return &http.Server{
ReadTimeout: 5 * time.Second,
ReadHeaderTimeout: 4 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}
} // newServer