// NewTLSConfig returns an initialized TLS configuration suitable for client // authentication. If caFile is non-empty, it will be loaded. func NewTLSConfig(caFile string, mutualTLS bool) (*tls.Config, error) { var c tls.Config // TLS 1.0 at a minimum (for mysql) c.MinVersion = tls.VersionTLS10 c.PreferServerCipherSuites = true if mutualTLS { log.Info("MutualTLS requested, client certificates will be verified") c.ClientAuth = tls.VerifyClientCertIfGiven } if caFile != "" { data, err := ioutil.ReadFile(caFile) if err != nil { return &c, err } c.ClientCAs = x509.NewCertPool() if !c.ClientCAs.AppendCertsFromPEM(data) { return &c, errors.New("No certificates parsed") } log.Info("Read in CA file:", caFile) } c.BuildNameToCertificate() return &c, nil }
// SecureCiphers updates a *tls.Config with a secure ciphersuite configuration. // If c is nil, a new config will be provided. func SecureCiphers(c *tls.Config) *tls.Config { if c == nil { c = &tls.Config{} } c.MinVersion = tls.VersionTLS10 // disable SSLv3 c.MaxVersion = tls.VersionTLS12 // enable TLS_FALLBACK_SCSV: https://go-review.googlesource.com/#/c/1776/ // Use all available ciphersuites minus RC4 and 3DES in a sane order. // This configuration has forward secrecy for supported browsers, and gets // an ‘A’ grade on SSL Labs. c.CipherSuites = []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, } c.PreferServerCipherSuites = true return c }
// SecureTLSConfig enforces the default minimum security settings for the // cluster. // TODO: allow override func SecureTLSConfig(config *tls.Config) *tls.Config { // Recommendations from https://wiki.mozilla.org/Security/Server_Side_TLS // Can't use SSLv3 because of POODLE and BEAST // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher // Can't use TLSv1.1 because of RC4 cipher usage config.MinVersion = tls.VersionTLS12 // In a legacy environment, allow cipher control to be disabled. if len(os.Getenv("OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES")) == 0 { config.PreferServerCipherSuites = true config.CipherSuites = []uint16{ // Ciphers below are selected and ordered based on the recommended "Intermediate compatibility" suite // Compare with available ciphers when bumping Go versions // // Available ciphers from last comparison (go 1.6): // TLS_RSA_WITH_RC4_128_SHA - no // TLS_RSA_WITH_3DES_EDE_CBC_SHA // TLS_RSA_WITH_AES_128_CBC_SHA // TLS_RSA_WITH_AES_256_CBC_SHA // TLS_RSA_WITH_AES_128_GCM_SHA256 // TLS_RSA_WITH_AES_256_GCM_SHA384 // TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - no // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA // TLS_ECDHE_RSA_WITH_RC4_128_SHA - no // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, // the next two are in the intermediate suite, but go1.6 http2 complains when they are included at the recommended index // fixed in https://github.com/golang/go/commit/b5aae1a2845f157a2565b856fb2d7773a0f7af25 in go1.7 // tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // tls.TLS_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, } } else { glog.Warningf("Potentially insecure TLS cipher suites are allowed in client connections because environment variable OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES is set") } return config }
// ListenAndServeTLSWithSNI serves TLS with Server Name Indication (SNI) support, which allows // multiple sites (different hostnames) to be served from the same address. This method is // adapted directly from the std lib's net/http ListenAndServeTLS function, which was // written by the Go Authors. It has been modified to support multiple certificate/key pairs. func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error { addr := srv.Addr if addr == "" { addr = ":https" } config := new(tls.Config) if srv.TLSConfig != nil { *config = *srv.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } // Here we diverge from the stdlib a bit by loading multiple certs/key pairs // then we map the server names to their certs var err error config.Certificates = make([]tls.Certificate, len(tlsConfigs)) for i, tlsConfig := range tlsConfigs { config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key) if err != nil { return err } } config.BuildNameToCertificate() // Customize our TLS configuration config.MinVersion = tlsConfigs[0].ProtocolMinVersion config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion config.CipherSuites = tlsConfigs[0].Ciphers config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites // TLS client authentication, if user enabled it err = setupClientAuth(tlsConfigs, config) if err != nil { return err } // Create listener and we're on our way conn, err := net.Listen("tcp", addr) if err != nil { return err } tlsListener := tls.NewListener(conn, config) return srv.Serve(tlsListener) }
func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error { addr := srv.Addr if addr == "" { addr = ":https" } config := new(tls.Config) if srv.TLSConfig != nil { *config = *srv.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } var err error config.Certificates = make([]tls.Certificate, len(tlsConfigs)) for i, tlsConfig := range tlsConfigs { config.Certificates[i], err = tls.LoadX509KeyPair(tlsConfig.Certificate, tlsConfig.Key) if err != nil { return err } } config.BuildNameToCertificate() config.MinVersion = tlsConfigs[0].ProtocolMinVersion config.MaxVersion = tlsConfigs[0].ProtocolMaxVersion config.CipherSuites = tlsConfigs[0].Ciphers config.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites err = setupClientAuth(tlsConfigs, config) if err != nil { return err } conn, err := net.Listen("tcp", addr) if err != nil { return err } tlsListener := tls.NewListener(conn, config) return srv.Serve(tlsListener) }
// SecureTLSConfig enforces the default minimum security settings for the // cluster. // TODO: allow override func SecureTLSConfig(config *tls.Config) *tls.Config { // Recommendations from https://wiki.mozilla.org/Security/Server_Side_TLS // Change default from SSLv3 to TLSv1.0 (because of POODLE vulnerability) config.MinVersion = tls.VersionTLS10 // In a legacy environment, allow cipher control to be disabled. if len(os.Getenv("OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES")) == 0 { config.PreferServerCipherSuites = true config.CipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, } } else { glog.Warningf("Potentially insecure TLS cipher suites are allowed in client connections because environment variable OPENSHIFT_ALLOW_DANGEROUS_TLS_CIPHER_SUITES is set") } return config }
func loadTLS(keyPath, certPath string) (*tls.Config, error) { tlsConfig := new(tls.Config) tlsConfig.PreferServerCipherSuites = true tlsConfig.CipherSuites = []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { logging.Error("config", "Error loading tls certificate and key files.") logging.Error("config", err.Error()) return nil, err } tlsConfig.Certificates = []tls.Certificate{cert} tlsConfig.BuildNameToCertificate() return tlsConfig, nil }
// MakeTLSConfig reduces configs into a single tls.Config. // If TLS is to be disabled, a nil tls.Config will be returned. func MakeTLSConfig(configs []*Config) (*tls.Config, error) { if configs == nil || len(configs) == 0 { return nil, nil } config := new(tls.Config) ciphersAdded := make(map[uint16]struct{}) configMap := make(configGroup) for i, cfg := range configs { if cfg == nil { // avoid nil pointer dereference below configs[i] = new(Config) continue } // Key this config by its hostname; this // overwrites configs with the same hostname configMap[cfg.Hostname] = cfg // Can't serve TLS and not-TLS on same port if i > 0 && cfg.Enabled != configs[i-1].Enabled { thisConfProto, lastConfProto := "not TLS", "not TLS" if cfg.Enabled { thisConfProto = "TLS" } if configs[i-1].Enabled { lastConfProto = "TLS" } return nil, fmt.Errorf("cannot multiplex %s (%s) and %s (%s) on same listener", configs[i-1].Hostname, lastConfProto, cfg.Hostname, thisConfProto) } // Union cipher suites for _, ciph := range cfg.Ciphers { if _, ok := ciphersAdded[ciph]; !ok { ciphersAdded[ciph] = struct{}{} config.CipherSuites = append(config.CipherSuites, ciph) } } // Can't resolve conflicting PreferServerCipherSuites settings if i > 0 && cfg.PreferServerCipherSuites != configs[i-1].PreferServerCipherSuites { return nil, fmt.Errorf("cannot both use PreferServerCipherSuites and not use it") } config.PreferServerCipherSuites = cfg.PreferServerCipherSuites // Go with the widest range of protocol versions if config.MinVersion == 0 || cfg.ProtocolMinVersion < config.MinVersion { config.MinVersion = cfg.ProtocolMinVersion } if cfg.ProtocolMaxVersion > config.MaxVersion { config.MaxVersion = cfg.ProtocolMaxVersion } // Go with the strictest ClientAuth type if cfg.ClientAuth > config.ClientAuth { config.ClientAuth = cfg.ClientAuth } } // Is TLS disabled? If so, we're done here. // By now, we know that all configs agree // whether it is or not, so we can just look // at the first one. if len(configs) == 0 || !configs[0].Enabled { return nil, nil } // Default cipher suites if len(config.CipherSuites) == 0 { config.CipherSuites = defaultCiphers } // For security, ensure TLS_FALLBACK_SCSV is always included if config.CipherSuites[0] != tls.TLS_FALLBACK_SCSV { config.CipherSuites = append([]uint16{tls.TLS_FALLBACK_SCSV}, config.CipherSuites...) } // Set up client authentication if enabled if config.ClientAuth != tls.NoClientCert { pool := x509.NewCertPool() clientCertsAdded := make(map[string]struct{}) for _, cfg := range configs { for _, caFile := range cfg.ClientCerts { // don't add cert to pool more than once if _, ok := clientCertsAdded[caFile]; ok { continue } clientCertsAdded[caFile] = struct{}{} // Any client with a certificate from this CA will be allowed to connect caCrt, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } if !pool.AppendCertsFromPEM(caCrt) { return nil, fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile) } } } config.ClientCAs = pool } // Associate the GetCertificate callback, or almost nothing we just did will work config.GetCertificate = configMap.GetCertificate return config, nil }
func main() { http.HandleFunc("/", newLoggingHandleFunc(rootHandler)) http.HandleFunc("/new", newLoggingHandleFunc(newHandler)) http.HandleFunc("/view/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(viewHandler)))) http.HandleFunc("/edit/", newLoggingHandleFunc(newGzipHandleFunc(titleHandler(editHandler)))) http.HandleFunc("/save/", newLoggingHandleFunc(titleHandler(saveHandler))) http.HandleFunc("/del/", newLoggingHandleFunc(titleHandler(delHandler))) http.HandleFunc("/front", newLoggingHandleFunc(newGzipHandleFunc(frontHandler))) http.HandleFunc("/hsts_hpkp", hsts_hpkp) log.SetPrefix("goWiki: ") log.Println("listening... on port", HTTPS_PORT) go func() { for { err := func() error { var OCSPC OCSPCert var err error cert, err := tls.LoadX509KeyPair(CERT, KEY) if err != nil { return err } OCSPC.cert = &cert if OCSPC.cert.Leaf, err = x509.ParseCertificate(OCSPC.cert.Certificate[0]); err != nil { return err } issuerRAW, err := ioutil.ReadFile(ISSUER) if err != nil { return err } for { var issuerPEM *pem.Block issuerPEM, issuerRAW = pem.Decode(issuerRAW) if issuerPEM == nil { break } if issuerPEM.Type == "CERTIFICATE" { OCSPC.issuer, err = x509.ParseCertificate(issuerPEM.Bytes) if err != nil { return err } } } if OCSPC.issuer == nil { return errors.New("no issuer") } OCSPC.req, err = ocsp.CreateRequest(OCSPC.cert.Leaf, OCSPC.issuer, nil) if err != nil { return err } err = OCSPC.updateStaple() if err != nil { return err } go OCSPC.stapleLoop() TLSConfig := new(tls.Config) TLSConfig.Certificates = []tls.Certificate{cert} TLSConfig.CipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} TLSConfig.PreferServerCipherSuites = true TLSConfig.MinVersion = tls.VersionTLS11 //MaxVersion needed because of bug with TLS_FALLBACK_SCSV gonna be fixed in go 1.5 TLSConfig.MaxVersion = tls.VersionTLS12 TLSConfig.NextProtos = []string{"http/1.1"} TLSConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { OCSPC.RLock() defer OCSPC.RUnlock() return OCSPC.cert, nil } ln, err := net.Listen("tcp", HTTPS_PORT) if err != nil { return err } tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, TLSConfig) return new(http.Server).Serve(tlsListener) }() if err != nil { log.Println(err) } time.Sleep(time.Second * TIMEOUT) } }() for { log.Println("redirecting from port", HTTP_PORT, "to", HTTPS_PORT) err := http.ListenAndServe(HTTP_PORT, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Frame-Options", "SAMEORIGIN") w.Header().Set("Server", "Jesus") log.Println("redirecting http", r.RemoteAddr, "to https", DOMAIN+HTTPS_PORT+r.URL.Path) http.Redirect(w, r, "https://"+DOMAIN+HTTPS_PORT+r.URL.Path, http.StatusMovedPermanently) })) if err != nil { log.Println(err) } time.Sleep(time.Second * TIMEOUT) } }
func main() { flag.Parse() log.Printf("Rosella v%s Initialising.", VERSION) //Init rosella itself server := NewServer() server.name = *serverName if *authFile != "" { log.Printf("Loading auth file: %q", *authFile) f, err := os.Open(*authFile) if err != nil { log.Fatal(err) } data := make([]byte, 1024) size, err := f.Read(data) if err != nil { log.Fatal(err) } lines := strings.Split(string(data[:size]), "\n") for _, line := range lines { if strings.HasPrefix(line, "#") { continue } fields := strings.Fields(line) if len(fields) == 2 { server.operatorMap[fields[0]] = fields[1] } } } if *motdFile != "" { log.Printf("Loading motd file: %q", *motdFile) f, err := os.Open(*motdFile) if err != nil { log.Fatal(err) } data := make([]byte, 1024) size, err := f.Read(data) if err != nil { log.Fatal(err) } server.motd = string(data[:size]) } go server.Run() tlsConfig := new(tls.Config) tlsConfig.PreferServerCipherSuites = true tlsConfig.CipherSuites = []uint16{ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} cert, err := tls.LoadX509KeyPair(*tlsCertFile, *tlsKeyFile) if err != nil { log.Printf("Error loading tls certificate and key files.") log.Printf(err.Error()) return } log.Printf("Loaded certificate and key successfully.") tlsConfig.Certificates = []tls.Certificate{cert} //Fills out tlsConfig.NameToCertificate tlsConfig.BuildNameToCertificate() tlsListener, err := tls.Listen("tcp", *ircAddress, tlsConfig) if err != nil { log.Printf("Could not open tls listener.") log.Printf(err.Error()) return } log.Printf("Listening on %s", *ircAddress) if syscall.Getuid() == 0 { if *groupId < 1 || *userId < 1 { log.Printf("Rosella may not be run as root. Please specify a non-root uid and gid that it may drop to.") return } if syscall.Setgid(*groupId) != nil { log.Printf("Failed to set gid to %i", *groupId) return } if syscall.Setuid(*userId) != nil { log.Printf("Failed to set uid to %i", *userId) return } } for { conn, err := tlsListener.Accept() if err != nil { log.Printf("Error accepting connection.") log.Printf(err.Error()) continue } server.HandleConnection(conn) } }