func serveHTTPS(ctx context.Context, httpServer *http.Server) error { log.Printf("Starting TLS server on %s", *httpsAddr) httpsServer := new(http.Server) *httpsServer = *httpServer httpsServer.Addr = *httpsAddr if !inProd { if *tlsCertFile == "" { return errors.New("unspecified --tlscert flag") } if *tlsKeyFile == "" { return errors.New("unspecified --tlskey flag") } return httpsServer.ListenAndServeTLS(*tlsCertFile, *tlsKeyFile) } cert, err := tlsCertFromGCS(ctx) if err != nil { return fmt.Errorf("error loading TLS certs from GCS: %v", err) } httpsServer.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{*cert}, } log.Printf("Listening for HTTPS on %v", *httpsAddr) ln, err := net.Listen("tcp", *httpsAddr) if err != nil { return err } return httpsServer.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, httpsServer.TLSConfig)) }
func serveHTTPS(ctx context.Context, httpServer *http.Server) error { log.Printf("Starting TLS server on %s", *httpsAddr) httpsServer := new(http.Server) *httpsServer = *httpServer httpsServer.Addr = *httpsAddr cacheFile := "letsencrypt.cache" if !inProd { if *tlsCertFile != "" && *tlsKeyFile != "" { return httpsServer.ListenAndServeTLS(*tlsCertFile, *tlsKeyFile) } // Otherwise use Let's Encrypt, i.e. same use case as in prod } else { cacheFile = prodLECache if err := os.MkdirAll(filepath.Dir(cacheFile), 0755); err != nil { return err } } var m letsencrypt.Manager if err := m.CacheFile(cacheFile); err != nil { return err } httpsServer.TLSConfig = &tls.Config{ GetCertificate: m.GetCertificate, } log.Printf("Listening for HTTPS on %v", *httpsAddr) ln, err := net.Listen("tcp", *httpsAddr) if err != nil { return err } return httpsServer.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, httpsServer.TLSConfig)) }
// AddSPDY adds SPDY support to srv, and must be called before srv begins serving. func AddSPDY(srv *http.Server) { npnStrings := npn() if len(npnStrings) <= 1 { return } if srv.TLSConfig == nil { srv.TLSConfig = new(tls.Config) } if srv.TLSConfig.NextProtos == nil { srv.TLSConfig.NextProtos = npnStrings } else { // Collect compatible alternative protocols. others := make([]string, 0, len(srv.TLSConfig.NextProtos)) for _, other := range srv.TLSConfig.NextProtos { if !strings.Contains(other, "spdy/") && !strings.Contains(other, "http/") { others = append(others, other) } } // Start with spdy. srv.TLSConfig.NextProtos = make([]string, 0, len(others)+len(npnStrings)) srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, npnStrings[:len(npnStrings)-1]...) // Add the others. srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, others...) srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, "http/1.1") } if srv.TLSNextProto == nil { srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) } for _, str := range npnStrings { switch str { case "spdy/2": srv.TLSNextProto[str] = func(s *http.Server, tlsConn *tls.Conn, handler http.Handler) { conn, err := NewServerConn(tlsConn, s, 2) if err != nil { log.Println(err) return } conn.Run() conn = nil runtime.GC() } case "spdy/3": srv.TLSNextProto[str] = func(s *http.Server, tlsConn *tls.Conn, handler http.Handler) { conn, err := NewServerConn(tlsConn, s, 3) if err != nil { log.Println(err) return } conn.Run() conn = nil runtime.GC() } } } }
func PrepareHTTPS(s *http.Server, cert string, key string, skipDev bool) error { // Checking for TLS default keys var certBytes, keyBytes []byte devCert := "devcert/cert.pem" devKey := "devcert/key.pem" // If only a single argument is set if (cert == "" || key == "") && (cert != "" || key != "") { log.Panic("You cannot specify only key or certificate") } // Using default certificate if cert == "" && !skipDev { if _, err := os.Stat(devCert); err == nil { if _, err := os.Stat(devKey); err == nil { log.Warning("===============================================================================") log.Warning("This instance will use development certificates, don't use them in production !") log.Warning("===============================================================================") cert = devCert key = devKey } else { log.Debug("No devcert key found: ", devKey) } } else { log.Debug("No devcert certificate found: ", devCert) } } if _, err := os.Stat(cert); err != nil { if _, err := os.Stat(key); err != nil { certBytes, keyBytes = GenerateDefaultTLS(cert, key) } } else { log.Info("Loading TLS Certificate: ", cert) log.Info("Loading TLS Private key: ", key) certBytes, err = ioutil.ReadFile(cert) keyBytes, err = ioutil.ReadFile(key) } certifs, err := tls.X509KeyPair(certBytes, keyBytes) if err != nil { log.Panic("Cannot parse certificates") } s.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{certifs}, } return nil }
// Start will start the SimpleServer at it's configured address. // If they are configured, this will start emitting metrics to Graphite, // register profiling, health checks and access logging. func (s *SimpleServer) Start() error { StartServerMetrics(s.cfg) healthHandler := RegisterHealthHandler(s.cfg, s.monitor, s.mux) s.cfg.HealthCheckPath = healthHandler.Path() srv := http.Server{ Handler: RegisterAccessLogger(s.cfg, s), MaxHeaderBytes: maxHeaderBytes, } l, err := net.Listen("tcp", fmt.Sprintf(":%d", s.cfg.HTTPPort)) if err != nil { return err } l = net.Listener(TCPKeepAliveListener{l.(*net.TCPListener)}) // add TLS if in the configs if s.cfg.TLSCertFile != nil && s.cfg.TLSKeyFile != nil { cert, err := tls.LoadX509KeyPair(*s.cfg.TLSCertFile, *s.cfg.TLSKeyFile) if err != nil { return err } srv.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, NextProtos: []string{"http/1.1"}, } l = tls.NewListener(l, srv.TLSConfig) } go func() { if err := srv.Serve(l); err != nil { Log.Error("encountered an error while serving listener: ", err) } }() Log.Infof("Listening on %s", l.Addr().String()) // join the LB go func() { exit := <-s.exit // let the health check clean up if it needs to if err := healthHandler.Stop(); err != nil { Log.Warn("health check Stop returned with error: ", err) } // stop the listener exit <- l.Close() }() return nil }
// AddSPDY adds SPDY support to srv, and must be called before srv begins serving. func AddSPDY(srv *http.Server) { if srv == nil { return } npnStrings := npn() if len(npnStrings) <= 1 { return } if srv.TLSConfig == nil { srv.TLSConfig = new(tls.Config) } if srv.TLSConfig.NextProtos == nil { srv.TLSConfig.NextProtos = npnStrings } else { // Collect compatible alternative protocols. others := make([]string, 0, len(srv.TLSConfig.NextProtos)) for _, other := range srv.TLSConfig.NextProtos { if !strings.Contains(other, "spdy/") && !strings.Contains(other, "http/") { others = append(others, other) } } // Start with spdy. srv.TLSConfig.NextProtos = make([]string, 0, len(others)+len(npnStrings)) srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, npnStrings[:len(npnStrings)-1]...) // Add the others. srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, others...) srv.TLSConfig.NextProtos = append(srv.TLSConfig.NextProtos, "http/1.1") } if srv.TLSNextProto == nil { srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) } for _, str := range npnStrings { switch str { case "spdy/2": srv.TLSNextProto[str] = spdy2.NextProto case "spdy/3": srv.TLSNextProto[str] = spdy3.NextProto case "spdy/3.1": srv.TLSNextProto[str] = spdy3.NextProto1 } } }
func configureTLS(server *http.Server) error { if _, err := os.Stat("cert.pem"); err != nil { log.Printf("Generating certificate...") generateCertificates("localhost") } cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem") if err != nil { return err } if server.TLSConfig == nil { server.TLSConfig = &tls.Config{} } server.TLSConfig.PreferServerCipherSuites = true server.TLSConfig.NextProtos = append(server.TLSConfig.NextProtos, "http/1.1") server.TLSConfig.Certificates = []tls.Certificate{cert} return nil }
func main() { http.HandleFunc("/", indexHandler) http.HandleFunc("/registerRequest", registerRequest) http.HandleFunc("/registerResponse", registerResponse) http.HandleFunc("/signRequest", signRequest) http.HandleFunc("/signResponse", signResponse) certs, err := tls.X509KeyPair([]byte(tlsCert), []byte(tlsKey)) if err != nil { log.Fatal(err) } log.Printf("Running on %s", appID) var s http.Server s.Addr = ":3483" s.TLSConfig = &tls.Config{Certificates: []tls.Certificate{certs}} log.Fatal(s.ListenAndServeTLS("", "")) }
func serveHTTPS(httpServer *http.Server) error { log.Printf("Starting TLS server on %s", *httpsAddr) httpsServer := new(http.Server) *httpsServer = *httpServer httpsServer.Addr = *httpsAddr cacheDir := autocert.DirCache("letsencrypt.cache") var domain string if !inProd { if *tlsCertFile != "" && *tlsKeyFile != "" { return httpsServer.ListenAndServeTLS(*tlsCertFile, *tlsKeyFile) } // Otherwise use Let's Encrypt, i.e. same use case as in prod if strings.HasPrefix(*httpsAddr, ":") { return errors.New("for Let's Encrypt, -https needs to start with a host name") } host, _, err := net.SplitHostPort(*httpsAddr) if err != nil { return err } domain = host } else { domain = "camlistore.org" cacheDir = autocert.DirCache(prodLECacheDir) } m := autocert.Manager{ Prompt: autocert.AcceptTOS, HostPolicy: autocert.HostWhitelist(domain), Cache: cacheDir, } if *adminEmail != "" { m.Email = *adminEmail } httpsServer.TLSConfig = &tls.Config{ GetCertificate: m.GetCertificate, } log.Printf("Listening for HTTPS on %v", *httpsAddr) ln, err := net.Listen("tcp", *httpsAddr) if err != nil { return err } return httpsServer.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, httpsServer.TLSConfig)) }
// ConfigureServer adds HTTP/2 support to http.Server. func ConfigureServer(hs *http.Server, conf *Server) { // Mostof the code in this function was copied from // https://github.com/bradfitz/http2/blob/master/server.go if conf == nil { conf = new(Server) } if hs.TLSConfig == nil { hs.TLSConfig = new(tls.Config) } hs.TLSConfig.NextProtos = append(hs.TLSConfig.NextProtos, H2Protos...) if hs.TLSNextProto == nil { hs.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){} } for _, proto := range H2Protos { hs.TLSNextProto[proto] = func(hs *http.Server, c *tls.Conn, h http.Handler) { conf.handleConn(hs, c, h) } } }
func serveHTTPS(httpServer *http.Server) error { log.Printf("Starting TLS server on %s", *httpsAddr) httpsServer := new(http.Server) *httpsServer = *httpServer httpsServer.Addr = *httpsAddr if !inProd { return httpsServer.ListenAndServeTLS(*tlsCertFile, *tlsKeyFile) } cert, err := tlsCertFromGCS() if err != nil { return err } httpsServer.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{*cert}, } ln, err := net.Listen("tcp", *httpsAddr) if err != nil { return err } return httpsServer.Serve(tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, httpsServer.TLSConfig)) }
// UpgradeServer operates similarly to ConfigureServer() with the exception that // it returns a clone copy of the original server that will be used to // exclusively serve HTTP/1.1 and HTTP/1.0 requests. The "HTTP/2 Configured" // server passed to UpgradeServer() should not be modified once this call has // been made, nor should it actively be listening for new connections. // // When an existing HTTP/1.1 connection requests an upgrade to h2c or h2c-14 mode, // the connection will be hijacked from the "clone server" (as returned by // UpgradeServer() and handed off to the internal http2 configured server. // // Ex usage: // // http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { // rw.Header().Set("Content-Type", "text/plain") // fmt.Fprintf(rw, "response to %v\n", r) // }) // // s := http2.UpgradeServer(&http.Server{Addr:":8080"},nil) // s.ListenAndServe() // // NB: Do *not* alter the returned server's Handler, as it is hooked in order to // perform the protocol switch. Any changes to uri handling must be made in the // "inner" server *before* it is passed to UpgradeServer(). The standard // http.DefaultServeMux will always be used as a last resort. // // NB: Note that HTTP/1.1 requests with bodies (i.e. HTTP POST) are not // supported in the initial Upgrade request but will work once the connection // is fully HTTP/2. Requests that have content entities will automatically // fallback to HTTP/1.1 (the upgrade silently fails but the normal handler // is invoked). func UpgradeServer(s *http.Server, conf *Server) *http.Server { if conf == nil { conf = new(Server) } handler := s.Handler if handler == nil { handler = http.DefaultServeMux } h1s := new(http.Server) *h1s = *s h1s.TLSConfig = nil h1s.TLSNextProto = nil h1s.Handler = &upgradeMux{ handler: handler, srv: s, conf: conf, } ConfigureServer(s, conf) return h1s }
// Start will start the SimpleServer at it's configured address. // If they are configured, this will start health checks and access logging. func (s *SimpleServer) Start() error { healthHandler := RegisterHealthHandler(s.cfg, s.monitor, s.mux) s.cfg.HealthCheckPath = healthHandler.Path() // if expvar, register on our router if s.cfg.Metrics.Type == metricscfg.Expvar { if s.cfg.Metrics.Path == "" { s.cfg.Metrics.Path = "/debug/vars" } s.mux.HandleFunc("GET", s.cfg.Metrics.Path, expvarHandler) } // if this is an App Engine setup, just run it here if s.cfg.appEngine { http.Handle("/", s) appengine.Main() return nil } wrappedHandler, err := NewAccessLogMiddleware(s.cfg.HTTPAccessLog, s) if err != nil { Log.Fatalf("unable to create http access log: %s", err) } srv := http.Server{ Handler: wrappedHandler, MaxHeaderBytes: maxHeaderBytes, ReadTimeout: readTimeout, WriteTimeout: writeTimeout, } l, err := net.Listen("tcp", fmt.Sprintf(":%d", s.cfg.HTTPPort)) if err != nil { return err } l = net.Listener(TCPKeepAliveListener{l.(*net.TCPListener)}) // add TLS if in the configs if s.cfg.TLSCertFile != nil && s.cfg.TLSKeyFile != nil { cert, err := tls.LoadX509KeyPair(*s.cfg.TLSCertFile, *s.cfg.TLSKeyFile) if err != nil { return err } srv.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, NextProtos: []string{"http/1.1"}, } l = tls.NewListener(l, srv.TLSConfig) } go func() { if err := srv.Serve(l); err != nil { Log.Error("encountered an error while serving listener: ", err) } }() Log.Infof("Listening on %s", l.Addr().String()) // join the LB go func() { exit := <-s.exit // let the health check clean up if it needs to if err := healthHandler.Stop(); err != nil { Log.Warn("health check Stop returned with error: ", err) } // flush any remaining metrics and close connections s.mets.Stop() // stop the listener exit <- l.Close() }() return nil }